Option Strict On
Option Explicit On

Imports System
Imports System.Text
Imports KadGen.MetadataWrapper
Imports KadGen.Utility2005


Public Class Defaults
   Private Const primarykey As String = "primarykey"
   Private Const mMultiParentDefaultPrimaryKeyColumnName As String = "PrimaryKeyGuid"
   Private Const mMultiParentDefaultTableColumnName As String = "TableName"
   Private Const mMultiParentDefaultTableName As String = "LocalizedData"
   Private Const mLocalizedPropertyAttribute As String = "IsLocalizedProperty"
   Private mDefaultGenerate As String = "CRUDS"
   Private mCreatePattern As String = "[Object]_Insert"
   Private mRetrievePattern As String = "[Object]_SelectOne"
   Private mRetrieveChildrenPattern As String = "[Object]_SelectChild"
   Private mRetrieveHierarchyPattern As String = "[Object]_SelectHierarchy"
   Private mRetrieveAlternatePattern As String = "_By_[Criteria]"
   Private mUpdatePattern As String = "[Object]_Update"
   Private mDeletePattern As String = "[Object]_Delete"
   Private mSetSelectPattern As String = "[Object]_SelectAll"
   Private mDefaultPriveleges As New MapPrivilegeCollection
   Private mKeyId As Int32
   Private mUnbackedColumnBehavior As KadGen.CodeGenerationSupport.UnbackedColumnBehavior
   'The assumption is we will have very few, but they will be used often so the ref is cached
   Private mMultiParentTables As List(Of DbsTable)
   Private mMultiParentObjectDefs As List(Of MapObjectDef)

   Friend Function UseUnbackedInSetSelect() As Boolean
      Return mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.RetrieveAndSetSelect Or _
                     mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.RetrieveAndSetSelectAndAssembly
   End Function

   Friend Function UseUnbackedInRetrieve() As Boolean
      Return mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.RetrieveAndSetSelect Or _
                     mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.RetrieveAndAssembly Or _
                     mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.RetrieveAndSetSelectAndAssembly Or _
                     mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.RetrieveOnly

   End Function

   Friend Function UseUnbackedInAssembly() As Boolean
      Return mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.AssemblyOnly Or _
                     mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.RetrieveAndSetSelectAndAssembly Or _
                     mUnbackedColumnBehavior = KadGen.CodeGenerationSupport.UnbackedColumnBehavior.RetrieveAndAssembly
   End Function


   ''' <summary>
   ''' 
   ''' </summary>
   ''' <param name="datastructure"></param>
   ''' <param name="mappingRoot"></param>
   ''' <remarks>This is done in this predicatble granular fashion to facilitate overrides</remarks>
   Friend Sub SetMapDefaults( _
            ByVal datastructure As DbsDataStructure, _
            ByVal mappingRoot As MapMappingRoot, _
            ByVal orders As List(Of Source), _
            ByVal useSchemaInWhereClause As Boolean, _
            ByVal unbackedColumnBehavior As KadGen.CodeGenerationSupport.UnbackedColumnBehavior)
      ' 20070726 KAD Changed to loop for each item before doing next, and other clean up behavior
      mappingRoot.UseSchemaInWhereClause = useSchemaInWhereClause

      mKeyId = 0
      mUnbackedColumnBehavior = unbackedColumnBehavior

      SetClassDefaults(mappingRoot)

      ' Before we can correctly add the new object defs, we have to flesh out the existing ones
      For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
         SetMapObjectDefDefaults(objectdef, datastructure)
      Next

      ' Add object defs inferred from data
      ' This also runs SetMapObjectDefDefaults on the new objects
      SetMapObjectDefCollectionDefaults(mappingRoot, datastructure, orders)
      ' Flesh out remaining information. 
      For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
         Dim table As DbsTable = GetDbsTable(datastructure, objectdef)
         Dim viewOrTable As IViewOrTable = GetDbsViewOrTable(datastructure, objectdef)

         If viewOrTable Is Nothing Then
            Utility.LogForUser("Could not find table for object def", LogId.CanNotFindTable, objectdef)
         End If

         If table IsNot Nothing Then
            SetMapChildCollectionDefaults(objectdef, objectdef.MapChildren, table)
            For Each child As MapChild In objectdef.MapChildren
               If String.IsNullOrEmpty(child.Ref) Then
                  ' Ref'd children are handled later because at this point we don't know if the ref'd object is created
                  SetMapChildDefaults(objectdef, child, table)
                  SetMapChildRelationKeyCollectionDefaults(child, table, objectdef)
                  ' Relation key details must be set later
               End If
            Next

         End If
      Next

      For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
         Dim table As DbsTable = GetDbsTable(datastructure, objectdef)
         SetLateChildren(objectdef, table)
      Next


      For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
         Dim table As DbsTable = GetDbsTable(datastructure, objectdef)
         SetMapForeignkeyCollectionDefaults(objectdef, objectdef.MapForeignKeys, table)
         For Each foreignKey As MapForeignKey In objectdef.MapForeignKeys
            SetMapForeignkeyDefaults(foreignKey, table)
            SetMapForeignRelationKeyCollectionDefaults(objectdef, foreignKey, foreignKey.MapRelationKeys, table)
            For Each relationkey As MapRelationKey In foreignKey.MapRelationKeys
               SetMapForeignRelationKeyDefaults(relationkey, table)
            Next
         Next
      Next

      For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
         Dim table As DbsTable = GetDbsTable(datastructure, objectdef)
         SetMapJoinCollectionDefaults(objectdef.MapJoinBases, table, datastructure)
         SetMapJoinCollectionDefaults(objectdef.MapJoinIns, table, datastructure)
      Next

      For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
         Dim table As DbsTable = GetDbsTable(datastructure, objectdef)
         Dim viewOrTable As IViewOrTable = GetDbsViewOrTable(datastructure, objectdef)
         SetMapPrivilegeCollectionDefaults(objectdef, objectdef.MapObjectPrivileges, viewOrTable)
         For Each privilege As MapPrivilege In objectdef.MapObjectPrivileges
            SetMapPrivilegeDefaults(privilege, viewOrTable)
         Next

         SetMapOrderByCollectionDefaults(objectdef, objectdef.MapOrderBies, viewOrTable)
         If objectdef IsNot Nothing AndAlso objectdef.MapOrderBies IsNot Nothing Then
            For i As Int32 = 0 To objectdef.MapOrderBies.Count - 1
               SetMapOrderByDefaults(objectdef.MapOrderBies(i), i, viewOrTable)
            Next
         End If

         SetMapPropertyCollectionDefaults(objectdef, objectdef.MapProperties, viewOrTable)
         For i As Int32 = 0 To objectdef.MapProperties.Count - 1
            SetMapPropertyDefaults(objectdef, objectdef.MapProperties(i), viewOrTable, i)
         Next

         ' Must be called after properties are set to ensure we know the primary keys
         SetMapWhereClauseDefaults(objectdef, useSchemaInWhereClause)

         SetMapRunSPCollectionDefaults(objectdef, objectdef.MapRunSPs, viewOrTable)
         For Each runSP As MapRunSP In objectdef.MapRunSPs
            SetMapRunSPDefaults(runSP, viewOrTable)
         Next

         SetMapUseForDescCollectionDefaults(objectdef, objectdef.MapUseForDescs, viewOrTable)
         For Each desc As MapUseForDesc In objectdef.MapUseForDescs
            SetMapUseForDescDefaults(desc, viewOrTable)
         Next

         SetMapUseForDescSetCollectionDefaults(objectdef, objectdef.MapUseForDescSets, viewOrTable)
         For Each descSet As MapUseForDescSet In objectdef.MapUseForDescSets
            SetMapUseForDescSetDefaults(descSet, viewOrTable)
         Next

         SetMapObjectSearchCriteriaCollectionDefaults(objectdef, objectdef.MapObjectSearchCriterias, viewOrTable)
         For Each criteria As MapSearchCriteria In objectdef.MapObjectSearchCriterias
            SetMapObjectSearchCriteriaDefaults(criteria, objectdef, viewOrTable)
         Next

         SetMapSetSearchCriteriaCollectionDefaults(objectdef, objectdef.MapSetSearchCriterias, viewOrTable)
         For Each criteria As MapSearchCriteria In objectdef.MapSetSearchCriterias
            SetMapSetSearchCriteriaDefaults(criteria, viewOrTable)
         Next

      Next

      For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
         Dim table As DbsTable = datastructure.DbsTables(objectdef.TableName)
         For Each child As MapChild In objectdef.MapChildren
            For Each key As MapRelationKey In child.MapRelationKeys
               SetLateMapChildRelationKeyDefaults(objectdef, child, key, table)
            Next
         Next
         SetLateDefaults(objectdef, datastructure)
         SetLateForeignKeys(objectdef, datastructure)
         SetLateUseForDesc(objectdef)
         SetLateObjectDisplayName(objectdef)
         'SetLateChildren(objectdef, table)
         SetLateAliases(objectdef)
         SetLateLookups(objectdef)
         SetLateObjectSearchCriterias(objectdef, datastructure)
         SetLateSetSearchCriterias(objectdef, datastructure)
         SetLateDependentProperties(objectdef, datastructure)
         SetLateJoinKeys(objectdef)
      Next

   End Sub

   Private Sub SetClassDefaults(ByVal mappingRoot As MapMappingRoot)
      If Not String.IsNullOrEmpty(mappingRoot.Generate) Then
         mDefaultGenerate = mappingRoot.Generate
      End If
      If Not String.IsNullOrEmpty(mappingRoot.CreatePattern) Then
         mCreatePattern = mappingRoot.CreatePattern
      End If
      If Not String.IsNullOrEmpty(mappingRoot.RetrievePattern) Then
         mRetrievePattern = mappingRoot.RetrievePattern
      End If
      If Not String.IsNullOrEmpty(mappingRoot.RetrieveChildrenPattern) Then
         mRetrieveChildrenPattern = mappingRoot.RetrieveChildrenPattern
      End If
      If Not String.IsNullOrEmpty(mappingRoot.RetrieveHierarchyPattern) Then
         mRetrieveHierarchyPattern = mappingRoot.RetrieveHierarchyPattern
      End If
      If Not String.IsNullOrEmpty(mappingRoot.RetrieveAlternatePattern) Then
         mRetrieveAlternatePattern = mappingRoot.RetrieveAlternatePattern
      End If
      If Not String.IsNullOrEmpty(mappingRoot.UpdatePattern) Then
         mUpdatePattern = mappingRoot.UpdatePattern
      End If
      If Not String.IsNullOrEmpty(mappingRoot.DeletePattern) Then
         mDeletePattern = mappingRoot.DeletePattern
      End If
      If Not String.IsNullOrEmpty(mappingRoot.SetSelectPattern) Then
         mSetSelectPattern = mappingRoot.SetSelectPattern
      End If
   End Sub

   'Friend Sub SetMapDefaults( _
   '         ByVal datastructure As DbsDataStructure, _
   '         ByVal mappingRoot As MapMappingRoot, _
   '         ByVal orders As List(Of Source), _
   '         ByVal useSchemaInWhereClause As Boolean, _
   '         ByVal unbackedColumnBehavior As KadGen.CodeGenerationSupport.UnbackedColumnBehavior)
   '   mappingRoot.UseSchemaInWhereClause = useSchemaInWhereClause

   '   mKeyId = 0
   '   mUnbackedColumnBehavior = unbackedColumnBehavior

   '   If Not String.IsNullOrEmpty(mappingRoot.Generate) Then
   '      mDefaultGenerate = mappingRoot.Generate
   '   End If
   '   If Not String.IsNullOrEmpty(mappingRoot.CreatePattern) Then
   '      mCreatePattern = mappingRoot.CreatePattern
   '   End If
   '   If Not String.IsNullOrEmpty(mappingRoot.RetrievePattern) Then
   '      mRetrievePattern = mappingRoot.RetrievePattern
   '   End If
   '   If Not String.IsNullOrEmpty(mappingRoot.RetrieveChildrenPattern) Then
   '      mRetrieveChildrenPattern = mappingRoot.RetrieveChildrenPattern
   '   End If
   '   If Not String.IsNullOrEmpty(mappingRoot.RetrieveAlternatePattern) Then
   '      mRetrieveAlternatePattern = mappingRoot.RetrieveAlternatePattern
   '   End If
   '   If Not String.IsNullOrEmpty(mappingRoot.UpdatePattern) Then
   '      mUpdatePattern = mappingRoot.UpdatePattern
   '   End If
   '   If Not String.IsNullOrEmpty(mappingRoot.DeletePattern) Then
   '      mDeletePattern = mappingRoot.DeletePattern
   '   End If
   '   If Not String.IsNullOrEmpty(mappingRoot.SetSelectPattern) Then
   '      mSetSelectPattern = mappingRoot.SetSelectPattern
   '   End If

   '   ' Before we can correctly add the new object defs, we have to flesh out the existing ones
   '   For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
   '      SetMapObjectDefDefaults(objectdef, datastructure)
   '   Next

   '   ' Add object defs inferred from data
   '   ' This also runs SetMapObjectDefDefaults on the new objects
   '   SetMapObjectDefCollectionDefaults(mappingRoot, datastructure, orders)
   '   ' Flesh out remaining information. 
   '   For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs

   '      Dim table As DbsTable = datastructure.DbsTables(objectdef.TableName)
   '      If table Is Nothing Then
   '         table = datastructure.DbsTables(objectdef.Name)
   '      End If
   '      Dim viewOrTable As IViewOrTable = table
   '      Dim view As DbsView = Nothing
   '      If viewOrTable Is Nothing Then
   '         view = datastructure.DbsViews(objectdef.ViewName)
   '         If view Is Nothing Then
   '            view = datastructure.DbsViews(objectdef.Name)
   '         End If
   '         viewOrTable = view
   '      End If

   '      If viewOrTable Is Nothing Then
   '         Utility.LogForUser("Could not find table for object def", LogId.CanNotFindTable, objectdef)
   '      End If

   '      If table IsNot Nothing Then
   '         SetMapChildCollectionDefaults(objectdef, objectdef.MapChildren, table)
   '         For Each child As MapChild In objectdef.MapChildren
   '            If String.IsNullOrEmpty(child.Ref) Then
   '               ' Ref'd children are handled later because at this point we don't know if the ref'd object is created
   '               SetMapChildDefaults(objectdef, child, table)
   '               SetMapChildRelationKeyCollectionDefaults(child, table, objectdef)
   '               ' Relation key details must be set later
   '            End If
   '         Next

   '         SetMapForeignkeyCollectionDefaults(objectdef, objectdef.MapForeignKeys, table)
   '         For Each foreignKey As MapForeignKey In objectdef.MapForeignKeys
   '            SetMapForeignkeyDefaults(foreignKey, table)
   '            SetMapForeignRelationKeyCollectionDefaults(objectdef, foreignKey, foreignKey.MapRelationKeys, table)
   '            For Each relationkey As MapRelationKey In foreignKey.MapRelationKeys
   '               SetMapForeignRelationKeyDefaults(relationkey, table)
   '            Next
   '         Next

   '         SetMapJoinCollectionDefaults(objectdef.MapJoinBases, table, datastructure)
   '         SetMapJoinCollectionDefaults(objectdef.MapJoinIns, table, datastructure)
   '      End If

   '      SetMapPrivilegeCollectionDefaults(objectdef, objectdef.MapObjectPrivileges, viewOrTable)
   '      For Each privilege As MapPrivilege In objectdef.MapObjectPrivileges
   '         SetMapPrivilegeDefaults(privilege, viewOrTable)
   '      Next

   '      SetMapOrderByCollectionDefaults(objectdef, objectdef.MapOrderBies, viewOrTable)
   '      If objectdef IsNot Nothing AndAlso objectdef.MapOrderBies IsNot Nothing Then
   '         For i As Int32 = 0 To objectdef.MapOrderBies.Count - 1
   '            SetMapOrderByDefaults(objectdef.MapOrderBies(i), i, viewOrTable)
   '         Next
   '      End If

   '      SetMapPropertyCollectionDefaults(objectdef, objectdef.MapProperties, viewOrTable)
   '      For i As Int32 = 0 To objectdef.MapProperties.Count - 1
   '         SetMapPropertyDefaults(objectdef, objectdef.MapProperties(i), viewOrTable, i)
   '      Next

   '      ' Must be called after properties are set to ensure we know the primary keys
   '      SetMapWhereClauseDefaults(objectdef, useSchemaInWhereClause)

   '      SetMapRunSPCollectionDefaults(objectdef, objectdef.MapRunSPs, viewOrTable)
   '      For Each runSP As MapRunSP In objectdef.MapRunSPs
   '         SetMapRunSPDefaults(runSP, viewOrTable)
   '      Next

   '      SetMapUseForDescCollectionDefaults(objectdef, objectdef.MapUseForDescs, viewOrTable)
   '      For Each desc As MapUseForDesc In objectdef.MapUseForDescs
   '         SetMapUseForDescDefaults(desc, viewOrTable)
   '      Next

   '      SetMapUseForDescSetCollectionDefaults(objectdef, objectdef.MapUseForDescSets, viewOrTable)
   '      For Each descSet As MapUseForDescSet In objectdef.MapUseForDescSets
   '         SetMapUseForDescSetDefaults(descSet, viewOrTable)
   '      Next

   '      SetMapObjectSearchCriteriaCollectionDefaults(objectdef, objectdef.MapObjectSearchCriterias, viewOrTable)
   '      For Each criteria As MapSearchCriteria In objectdef.MapObjectSearchCriterias
   '         SetMapObjectSearchCriteriaDefaults(criteria, objectdef, viewOrTable)
   '      Next

   '      SetMapSetSearchCriteriaCollectionDefaults(objectdef, objectdef.MapSetSearchCriterias, viewOrTable)
   '      For Each criteria As MapSearchCriteria In objectdef.MapSetSearchCriterias
   '         SetMapSetSearchCriteriaDefaults(criteria, viewOrTable)
   '      Next

   '   Next

   '   For Each objectdef As MapObjectDef In mappingRoot.MapMapping.MapObjectDefs
   '      Dim table As DbsTable = datastructure.DbsTables(objectdef.TableName)
   '      For Each child As MapChild In objectdef.MapChildren
   '         For Each key As MapRelationKey In child.MapRelationKeys
   '            SetLateMapChildRelationKeyDefaults(objectdef, child, key, table)
   '         Next
   '      Next
   '      SetLateDefaults(objectdef, datastructure)
   '      SetLateForeignKeys(objectdef, datastructure)
   '      SetLateUseForDesc(objectdef)
   '      SetLateObjectDisplayName(objectdef)
   '      SetLateChildren(objectdef, table)
   '      SetLateAliases(objectdef)
   '      SetLateLookups(objectdef)
   '      SetLateObjectSearchCriterias(objectdef, datastructure)
   '      SetLateSetSearchCriterias(objectdef, datastructure)
   '      SetLateDependentProperties(objectdef, datastructure)
   '      SetLateJoinKeys(objectdef)
   '   Next

   'End Sub

   Protected Sub SetMapObjectDefCollectionDefaults( _
            ByVal mappingRoot As MapMappingRoot, _
            ByVal datastructure As DbsDataStructure, _
            ByVal orders As List(Of Source))
      ' TODO: Check for no inferrence
      For Each source As Source In orders

         Select Case source
            Case source.Table
               LoadFromTables(mappingRoot, datastructure)
            Case source.View
               LoadFromView(mappingRoot, datastructure)
            Case source.StoreProc
               LoadFromSP(mappingRoot, datastructure)
            Case Else

         End Select

      Next
   End Sub

   Protected Sub LoadFromTables( _
            ByVal mappingRoot As MapMappingRoot, _
            ByVal dataStructure As DbsDataStructure)
      For Each table As DbsTable In dataStructure.DbsTables
         Dim matches As MapObjectDefCollection = mappingRoot.GetByTableName(table.OriginalName)
         If matches Is Nothing OrElse matches.Count = 0 Then
            Dim objectDef As MapObjectDef = New MapObjectDef(mappingRoot, table.OriginalName, ObjectDefFrom.Table)
            mappingRoot.MapMapping.MapObjectDefs.Add(objectDef)
            SetMapObjectDefDefaults(objectDef, dataStructure)
         End If
      Next
   End Sub

   Protected Sub LoadFromView( _
            ByVal mappingRoot As MapMappingRoot, _
            ByVal dataStructure As DbsDataStructure)
      For Each View As DbsView In dataStructure.DbsViews
         Dim matches As MapObjectDefCollection = mappingRoot.GetByTableName(View.Name)
         If matches Is Nothing OrElse matches.Count = 0 Then
            Dim objectDef As MapObjectDef = New MapObjectDef(mappingRoot, Nothing, ObjectDefFrom.View, View.OriginalName)
            mappingRoot.MapMapping.MapObjectDefs.Add(objectDef)
            SetMapObjectDefDefaults(objectDef, dataStructure)
         End If
      Next
   End Sub

   Protected Sub LoadFromSP( _
            ByVal mappingRoot As MapMappingRoot, _
            ByVal dataStructure As DbsDataStructure)
      For Each sp As DbsStoredProc In dataStructure.GetRetrieveStoredProcs()
         ' Find main table name
         ' TODO: Work on retrieving the SetSelect for ReadOnly objects
         Dim pattern As String = mappingRoot.RetrievePattern
         Dim name As String = Tools.ExtractObjectName(pattern, sp.Name)
         If String.IsNullOrEmpty(name) Then
            ' This stored proc did not match retrieve pattern
            Continue For
         End If

         Dim baseName As String = name
         Dim objectDef As MapObjectDef = mappingRoot.GetByObjectName(name)
         Dim table As DbsTable = FindTable(dataStructure, name, AddressOf FindTable)
         If objectDef Is Nothing Then

            If AlreadyCreated(mappingRoot, name) Then
               Continue For
            End If

            If table Is Nothing Then
               ' Start over with new algorithm
               name = baseName
               table = FindTable(dataStructure, name, AddressOf FindTableBySingularName)
               If AlreadyCreated(mappingRoot, name) Then
                  Continue For
               End If
               If table Is Nothing Then
                  Utility.LogForUser("Could not find base table for stored proc", LogId.CanNotFindTable, sp)
               End If
            End If
            If table IsNot Nothing Then
               objectDef = New MapObjectDef(mappingRoot, table.OriginalName, ObjectDefFrom.StoredProc)
               mappingRoot.MapMapping.MapObjectDefs.Add(objectDef)
            End If
         End If
         If objectDef IsNot Nothing Then
            SetMapObjectDefDefaults(objectDef, dataStructure)
         End If
      Next
   End Sub

   Private Function AlreadyCreated(ByVal mappingRoot As MapMappingRoot, ByVal name As String) As Boolean
      Dim matches As MapObjectDefCollection = mappingRoot.GetByTableName(name)
      If matches IsNot Nothing AndAlso matches.Count > 0 Then
         Return True
      End If
      Dim match As MapObjectDef = mappingRoot.GetByObjectName(name)
      If match IsNot Nothing Then
         Return True
      End If
   End Function

   Private Delegate Function SearchForDelegate( _
            ByVal dataStructure As DbsDataStructure, _
            ByVal name As String) _
            As DbsTable

   Private Function FindTable( _
            ByVal dataStructure As DbsDataStructure, _
            ByRef name As String, _
            ByVal deleg As SearchForDelegate) _
            As DbsTable
      Dim table As DbsTable = deleg(dataStructure, name)
      Do While table Is Nothing
         ' TODO: Consider splitting this as caps as well?
         Dim pos As Int32 = name.LastIndexOf("_")
         ' Zero position string means underscore at beginning
         If pos <= 0 Then
            Exit Do
         End If
         name = name.Substring(0, pos)
         table = deleg(dataStructure, name)
      Loop
      Return table
   End Function

   Private Function FindTable( _
            ByVal dataStructure As DbsDataStructure, _
            ByVal name As String) _
            As DbsTable
      Dim table As DbsTable = dataStructure.DbsTables(name)
      If table Is Nothing Then
         Dim singularname As String = Tools.GetSingular(name)
         table = dataStructure.DbsTables(singularname)
      End If
      If table Is Nothing Then
         Dim pluralName As String = Tools.GetPlural(name)
         table = dataStructure.DbsTables(pluralName)
      End If
      Return table
   End Function

   Private Function FindTableBySingularName( _
            ByVal dataStructure As DbsDataStructure, _
            ByVal name As String) _
            As DbsTable
      Return dataStructure.DbsTables.GetTableBySingularName(name)
   End Function

   Protected Sub SetMapObjectDefDefaults( _
            ByVal objectDef As MapObjectDef, _
            ByVal datastructure As DbsDataStructure)
      ' TODO: Support prefix stuff from arguments such as lookups
      Dim table As DbsTable = GetDbsTable(datastructure, objectDef)
      Dim view As DbsView = GetDbsView(datastructure, objectDef)
      If table Is Nothing AndAlso view Is Nothing Then
         Utility.LogForUser("Could not find table for ObjectDef. The object def in the ORM file may not correspond to an existing table.", LogId.CanNotFindTable, objectDef)
      End If
      Dim singularName As String = Nothing
      ' The next two variables do not appear to be in use
      Dim insertPriority As Int32 = 0
      Dim deletePriority As Int32 = 0
      Dim originalName As String = Nothing
      Dim prefix As String = Nothing
      If table IsNot Nothing Then
         If String.IsNullOrEmpty(objectDef.TableName) Then
            objectDef.TableName = table.OriginalName
         End If
         If String.IsNullOrEmpty(objectDef.UnderlyingTable) Then
            objectDef.UnderlyingTable = table.Name
         End If
         singularName = table.SingularName
         insertPriority = table.InsertPriority.GetValueOrDefault
         deletePriority = table.DeletePriority.GetValueOrDefault
         originalName = table.OriginalName
         prefix = table.Prefix
      Else
         If view IsNot Nothing And Not String.IsNullOrEmpty(objectDef.TableName) Then
            objectDef.ViewName = view.Name
            singularName = view.SingularName
            originalName = view.OriginalName
            prefix = view.Prefix
         End If
      End If
      If String.IsNullOrEmpty(objectDef.Name) Then
         If Not String.IsNullOrEmpty(objectDef.ObjectName) Then
            objectDef.Name = objectDef.ObjectName
         ElseIf Not String.IsNullOrEmpty(singularName) Then
            objectDef.Name = singularName
         End If
      End If
      objectDef.Name = Tools.GetSingular(objectDef.Name)
      If String.IsNullOrEmpty(objectDef.ObjectName) Then
         objectDef.ObjectName = objectDef.Name
      End If
      If String.IsNullOrEmpty(objectDef.Caption) Then
         objectDef.Caption = Tools.GetCaption(objectDef.Name)
      End If
      If String.IsNullOrEmpty(objectDef.Generate) Then
         objectDef.Generate = mDefaultGenerate
      End If
      ' TODO: We have to support nullability to manage IncludeChildren, Insert and delete priority
      objectDef.InsertPriority = insertPriority
      objectDef.DeletePriority = deletePriority
      If table IsNot Nothing And Not objectDef.NoImplicitLookup.GetValueOrDefault Then
         objectDef.IsLookup = table.IsLookup
      End If
      ' TODO: Add IsLookup from argument prefix
      ' NOTE: Lookup status is checked after all properties added
      ' TODO: Add nonprefixed originalname from argument information
      If String.IsNullOrEmpty(objectDef.OriginalName) Then
         objectDef.OriginalName = originalName
      End If
      If String.IsNullOrEmpty(objectDef.PluralName) Then
         objectDef.PluralName = Tools.GetPlural(objectDef.Name)
      End If
      If String.IsNullOrEmpty(objectDef.PluralCaption) Then
         objectDef.PluralCaption = Tools.GetCaption(objectDef.PluralName)
      End If
      If String.IsNullOrEmpty(objectDef.Prefix) Then
         objectDef.Prefix = prefix
      End If
      If String.IsNullOrEmpty(objectDef.SingularName) Then
         ' Currently object def name is forced to singular so this is redundant
         objectDef.SingularName = objectDef.Name
      End If

      If String.IsNullOrEmpty(objectDef.NonPrefixedOriginalName) Then
         If Not String.IsNullOrEmpty(prefix) Then
            objectDef.NonPrefixedOriginalName = objectDef.OriginalName.Replace(prefix, "")
         Else
            objectDef.NonPrefixedOriginalName = objectDef.OriginalName
         End If
      End If

      If objectDef.NoGenAtAll.GetValueOrDefault Then
         objectDef.NoGenStoredProc = True
         objectDef.NoGenObject = True
         objectDef.NoGenUI = True
      End If

      If table IsNot Nothing AndAlso table.Attributes IsNot Nothing Then
         For Each attribute As KadGen.MetadataWrapper.Attribute In table.Attributes
            ' If there is a conflict, the existing in the ORM file wins
            objectDef.AddCustomAttribute(attribute, False)
         Next
      End If

      ' TODO: Look into viewname 

   End Sub

   Private Function GetDbsTable( _
            ByVal dataStructure As DbsDataStructure, _
            ByVal objectDef As MapObjectDef) _
            As DbsTable
      Dim table As DbsTable = Nothing
      If Not String.IsNullOrEmpty(objectDef.TableName) Then
         table = dataStructure.DbsTables(objectDef.TableName)
      Else
         table = dataStructure.DbsTables(objectDef.Name)
         If table Is Nothing Then
            Dim singularname As String = Tools.GetSingular(objectDef.Name)
            table = dataStructure.DbsTables(singularname)
         End If
         If table Is Nothing Then
            Dim pluralName As String = Tools.GetPlural(objectDef.Name)
            table = dataStructure.DbsTables(pluralName)
         End If
      End If
      Return table
   End Function

   Private Function GetDbsView( _
            ByVal dataStructure As DbsDataStructure, _
            ByVal objectDef As MapObjectDef) _
            As DbsView
      Dim View As DbsView = Nothing
      If Not String.IsNullOrEmpty(objectDef.ViewName) Then
         View = dataStructure.DbsViews(objectDef.ViewName)
      Else
         View = dataStructure.DbsViews(objectDef.Name)
         If View Is Nothing Then
            Dim singularname As String = Tools.GetSingular(objectDef.Name)
            View = dataStructure.DbsViews(singularname)
         End If
         If View Is Nothing Then
            Dim pluralName As String = Tools.GetPlural(objectDef.Name)
            View = dataStructure.DbsViews(pluralName)
         End If
      End If
      Return View
   End Function

   Private Function GetDbsViewOrTable( _
            ByVal dataStructure As DbsDataStructure, _
            ByVal objectDef As MapObjectDef) _
            As IViewOrTable
      Dim table As DbsTable = GetDbsTable(dataStructure, objectDef)
      Dim viewOrTable As IViewOrTable = table
      If viewOrTable Is Nothing Then
         viewOrTable = GetDbsView(dataStructure, objectDef)
      End If
      Return viewOrTable
   End Function

   Protected Sub SetMapChildCollectionDefaults( _
            ByVal objectDef As MapObjectDef, _
            ByVal children As MapChildCollection, _
            ByVal table As DbsTable)
      Dim childId As String
      Dim existingChildren As New List(Of String)
      ' Get list of current children for later use
      For Each child As MapChild In objectDef.MapChildren
         Dim tempName As String = child.TableName
         If String.IsNullOrEmpty(tempName) Then
            tempName = child.Name
         End If
         Dim childTableTemp As DbsChildTable = table.DbsChildTables.GetChildTable(tempName)
         If childTableTemp IsNot Nothing Then
            childId = GetChildId(childTableTemp)
            existingChildren.Add(childId)
         End If
      Next
      If objectDef.IncludeChildren.GetValueOrDefault OrElse _
            (children.Count = 0 AndAlso _
            Not objectDef.NoChildren.GetValueOrDefault AndAlso _
            Not objectDef.MapMapping.NoInferrence.GetValueOrDefault AndAlso _
            Not objectDef.MapMapping.NoChildren.GetValueOrDefault AndAlso _
            Not objectDef.IsLookup.GetValueOrDefault) Then
         For Each childTable As DbsChildTable In table.DbsChildTables
            AddChild(objectDef, table, childTable, existingChildren)
         Next
      End If

      If table.DbsTableColumns.HasColumnWithTrueAttribute(mLocalizedPropertyAttribute) Then
         Dim localizedDataTable As DbsTable = table.DbsDataStructures.GetTable(mMultiParentDefaultTableName)
         Dim multiParentChild As MapMultiParentChild = objectDef.MapMultiParentChildren.GetMultiParentChild(mMultiParentDefaultTableName)
         If localizedDataTable IsNot Nothing AndAlso multiParentChild Is Nothing Then
            objectDef.MapMultiParentChildren.Add(New MapMultiParentChild( _
                  objectDef.MapMappingRoot, mMultiParentDefaultTableName, _
                  mMultiParentDefaultTableColumnName, mMultiParentDefaultPrimaryKeyColumnName))
         End If
      End If

      ' multiparent children are expected to be things like localized data and added data that are 
      ' included regardless of thethe IncludeChildren marking. 
      For Each multiParentChild As MapMultiParentChild In objectDef.MapMultiParentChildren
         AddMultiParentChildTable(table.DbsDataStructures, multiParentChild, objectDef, table, existingChildren)
      Next
   End Sub

   Private Sub AddChild( _
               ByVal objectDef As MapObjectDef, _
               ByVal table As DbsTable, _
               ByVal childTable As DbsChildTable, _
               ByVal existingChildren As List(Of String))
      Dim isOK As Boolean = True
      Dim childId As String
      childId = GetChildId(childTable)
      If existingChildren.Contains(childId) Then
         Return
      Else
         existingChildren.Add(childId)
         If String.Compare(table.OriginalName, childTable.Name, StringComparison.InvariantCultureIgnoreCase) = 0 Then
            ' Check that relations are different
            isOK = False
            For i As Int32 = 0 To childTable.DbsChildKeyFields.Count - 1
               If childTable.DbsChildKeyFields(i).Name <> childTable.DbsParentKeyFields(i).Name Then
                  isOK = True
                  Exit For
               End If
            Next
         End If
         If isOK Then
            Dim child As New MapChild(objectDef.MapMappingRoot, _
                     Nothing, Nothing, Nothing, childTable.Name, _
                     Nothing, Nothing, Nothing, Nothing, Nothing, _
                     Nothing, Nothing, Nothing, Nothing, Nothing)
            objectDef.MapChildren.Add(child)
            SetMapChildRelationKeys(objectDef, child, table, childTable)
         Else
            Utility.LogForUser("Invalid self join - primary key to primary key", LogId.InvalidChildRelation, table, childTable)
         End If
      End If
   End Sub

   Private Function GetChildId(ByVal childTable As DbsChildTable) As String
      Dim childId As String = childTable.Name
      For i As Int32 = 0 To childTable.DbsChildKeyFields.Count - 1
         childId &= "|" & childTable.DbsChildKeyFields(i).Name
      Next
      Return childId
   End Function

   Private Sub AddMultiParentChildTable( _
            ByVal dataStructures As DbsDataStructureCollection, _
            ByVal multiParentChild As MapMultiParentChild, _
            ByVal objectDef As MapObjectDef, _
            ByVal table As DbsTable, _
            ByVal existingChildren As List(Of String))
      Dim multiChildTable As DbsTable = GetMultiParentTable(multiParentChild.Name, table.DbsDataStructures)
      If multiChildTable Is Nothing Then
         Return
      End If
      If String.IsNullOrEmpty(multiParentChild.PrimaryKeyColumnName) Then
         multiParentChild.PrimaryKeyColumnName = mMultiParentDefaultPrimaryKeyColumnName
      End If
      Dim childId As String = multiParentChild.Name & "|" & multiParentChild.PrimaryKeyColumnName
      If existingChildren.Contains(childId) Then
         Return
      End If
      Dim newChild As MapChild = New MapChild(objectDef.MapMappingRoot, _
                  Nothing, Nothing, Nothing, multiChildTable.Name, _
                  Nothing, Nothing, Nothing, Nothing, Nothing, _
                  Nothing, Nothing, Nothing, Nothing, Nothing)
      objectDef.MapChildren.Add(newChild)
      Dim primaryKeys As DbsTableColumnCollection = table.DbsTableColumns.PrimaryKeys
      If primaryKeys.Count <> 1 Then
         Utility.LogForUser("MultiParentChildTables must have a single column primary key", _
                  LogId.InvalidPrimaryKeyForMultiParentData, table)
         Return
      End If
      newChild.MapRelationKeys.Add(New MapRelationKey(objectDef.MapMappingRoot, _
               primaryKeys(0).Name, multiParentChild.PrimaryKeyColumnName, _
               table.OriginalName, multiParentChild.Name, _
               table.OriginalName, multiParentChild.Name, _
               Nothing, Nothing, _
               Nothing, Nothing))
      AddMultiParentForeignKey(multiParentChild, objectDef, newChild, primaryKeys(0).Name)
   End Sub

   Private Sub AddMultiParentForeignKey( _
            ByVal multiParentChild As MapMultiParentChild, _
            ByVal objectDef As MapObjectDef, _
            ByVal child As MapChild, _
            ByVal parentPrimaryKeyName As String)
      Dim multiobjectDef As MapObjectDef = GetMultiParentObjectDef(multiParentChild.Name, objectDef.MapMapping)
      Dim newFKey As MapForeignKey = New MapForeignKey(objectDef.MapMappingRoot, _
               objectDef.Name, objectDef.TableName, objectDef.Schema)
      multiobjectDef.MapForeignKeys.Add(newFKey)
      multiobjectDef.IsMultiParentChild = True
      newFKey.MapChild = child
      newFKey.MapParentObjectDef = objectDef
   End Sub

   Private Function GetMultiParentTable(ByVal tableName As String, ByVal datastructures As DbsDataStructureCollection) As DbsTable
      If mMultiParentTables Is Nothing Then
         mMultiParentTables = New List(Of DbsTable)
      End If
      For Each table As DbsTable In mMultiParentTables
         If table.Name.Equals(tableName, StringComparison.InvariantCultureIgnoreCase) Then
            Return table
         End If
      Next
      For Each table As DbsTable In datastructures(0).DbsTables
         If table.Name.Equals(tableName, StringComparison.InvariantCultureIgnoreCase) Then
            mMultiParentTables.Add(table)
            Return table
         End If
      Next
      Return Nothing
   End Function

   Private Function GetMultiParentObjectDef(ByVal name As String, ByVal mapping As MapMapping) As MapObjectDef
      If mMultiParentObjectDefs Is Nothing Then
         mMultiParentObjectDefs = New List(Of MapObjectDef)
      End If
      For Each objectDef As MapObjectDef In mMultiParentObjectDefs
         If objectDef.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase) Then
            Return objectDef
         End If
      Next
      For Each objectDef As MapObjectDef In mapping.MapObjectDefs
         If objectDef.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase) Then
            mMultiParentObjectDefs.Add(objectDef)
            Return objectDef
         End If
      Next
      Return Nothing
   End Function

   Protected Sub SetMapChildDefaults( _
            ByVal objectDef As MapObjectDef, _
            ByVal child As MapChild, _
            ByVal table As DbsTable)
      ' NOTE: Ref'd objects are set in the next method. They should genearally parallel
      Dim tableName As String = child.TableName
      Dim childTable As DbsTable = table.DbsDataStructures.GetTable(tableName)
      If childTable Is Nothing Then
         tableName = Tools.GetSingular(child.Name)
         childTable = table.DbsDataStructures.GetTable(tableName)
      End If
      If childTable Is Nothing Then
         tableName = Tools.GetPlural(tableName)
         childTable = table.DbsDataStructures.GetTable(tableName)
      End If
      If child.MapRelationKeys.Count = 0 Then
         Dim childChildTable As DbsChildTable = table.DbsChildTables.GetChildTable(childTable.OriginalName)
         SetMapChildRelationKeys(objectDef, child, table, childChildTable)
      End If
      Dim childObjectDef As MapObjectDef = Nothing
      childObjectDef = objectDef.MapMappingRoot.GetByObjectName(child.ObjectName)
      If childObjectDef Is Nothing Then
         childObjectDef = objectDef.MapMappingRoot.GetByObjectName(child.Name)
      End If
      ' IT is not an error if the childObjectDef is not found at this point. It will be used if entered in the ORM file only
      If Not String.IsNullOrEmpty(child.Name) AndAlso childTable Is Nothing AndAlso childObjectDef IsNot Nothing Then
         tableName = childObjectDef.TableName
         childTable = table.DbsDataStructures.GetTable(tableName)
      End If
      If childTable Is Nothing Then
         Utility.LogForUser("Could not find child table", LogId.CanNotFindTable, objectDef, child)
      End If
      If childTable IsNot Nothing Then
         If String.IsNullOrEmpty(child.Schema) Then
            child.Schema = childTable.Schema
         End If
         If String.IsNullOrEmpty(child.Name) Then
            child.Name = childTable.SingularName
         End If
      End If
      If childObjectDef Is Nothing Then
         childObjectDef = child.MapMappingRoot.GetByObjectName(child.Name)
      End If
      If childObjectDef Is Nothing Then
         Utility.LogForUser("Could not find child ObjectDef", LogId.CanNotFindTable, objectDef, child)
      End If
      ' In the following, the child object def has always been created, it just contains all empty values
      If child.MapChildObjectDef Is Nothing OrElse String.IsNullOrEmpty(child.MapChildObjectDef.Name) Then
         child.MapChildObjectDef = childObjectDef
      End If
      If String.IsNullOrEmpty(child.ObjectName) Then
         child.ObjectName = child.Name
      End If
      If String.IsNullOrEmpty(child.Alias) Then
         Dim testAlias As String = childTable.Name
         Dim match As Int32 = 0
         For Each otherChild As MapChild In objectDef.MapChildren
            If otherChild Is child Then
               Exit For
            End If
            If otherChild.Alias Is Nothing Then
               If otherChild.TableName = testAlias Then
                  match += 1
               End If
            Else
               If otherChild.Alias = testAlias Then
                  match += 1
               End If
            End If
         Next
         If match = 0 Then
            child.Alias = testAlias
         Else
            child.Alias = testAlias & match.ToString()
         End If
      End If
      If String.IsNullOrEmpty(child.TableName) Then
         child.TableName = childTable.OriginalName
      End If
      SetMapChildCommonValues(objectDef, child)

      ' TODO: Deal with child.RelationType

   End Sub

   Private Sub SetMapChildCommonValues(ByVal objectDef As MapObjectDef, ByVal child As MapChild)
      If String.IsNullOrEmpty(child.CasedName) Then
         child.CasedName = Utility.GetCasedName(child.Name)
      End If
      If String.IsNullOrEmpty(child.TempChildTableName) Then
         child.TempChildTableName = child.ObjectName
      End If
      If String.IsNullOrEmpty(child.TempParentTableName) Then
         child.TempParentTableName = objectDef.ObjectName
      End If
   End Sub

   Protected Sub SetLateChildren(ByVal objectDef As MapObjectDef, ByVal table As DbsTable)
      Dim position As Int32 = 0
      Dim hasSelfJoin As Boolean = False
      For Each child As MapChild In objectDef.MapChildren
         If Not String.IsNullOrEmpty(child.Ref) Then
            SetRefChildDefaults(objectDef, child, table)
            SetMapChildRelationKeyCollectionDefaults(child, table, objectDef)
         End If
         If child.TableName = objectDef.TableName Then
            hasSelfJoin = True
         End If
         child.ChildFlag = CULng(2 ^ position)
         position += 1
      Next
      objectDef.IsParent = objectDef.MapChildren.Count > 0
      objectDef.IsChild = objectDef.MapMapping.AppearsAsChild(objectDef)
      objectDef.HasSelfJoin = hasSelfJoin
   End Sub

   Protected Sub SetRefChildDefaults( _
         ByVal objectDef As MapObjectDef, _
         ByVal child As MapChild, _
         ByVal table As DbsTable)
      ' NOTE: Non ref'd objects are set in the previous method. These methods should genearally parallel
      Dim childObjectDef As MapObjectDef = objectDef.MapMappingRoot.GetObjectDef(child.Ref)
      If childObjectDef Is Nothing Then
         Utility.LogForUser("Could not find ref'd object", LogId.CanNotFindObjectDef, objectDef, child)
         Return
      End If
      If String.IsNullOrEmpty(child.Schema) Then
         child.Schema = childObjectDef.Schema
      End If
      If String.IsNullOrEmpty(child.Name) Then
         child.Name = childObjectDef.Name
      End If
      child.MapChildObjectDef = childObjectDef
      If String.IsNullOrEmpty(child.ObjectName) Then
         child.ObjectName = childObjectDef.ObjectName
      End If
      If String.IsNullOrEmpty(child.Alias) Then
         ' Changed 4/22/07 because of issues with explicitly named children in Universal security
         child.Alias = childObjectDef.TableName
      End If
      If String.IsNullOrEmpty(child.TableName) Then
         child.TableName = childObjectDef.TableName
      End If
      SetMapChildCommonValues(objectDef, child)
      'If String.IsNullOrEmpty(child.CasedName) Then
      '   child.CasedName = Utility.GetCasedName(child.Name)
      'End If
      'If String.IsNullOrEmpty(child.TempChildTableName) Then
      '   child.TempChildTableName = childObjectDef.ObjectName
      'End If
      'If String.IsNullOrEmpty(child.TempParentTableName) Then
      '   child.TempParentTableName = objectDef.TableName
      'End If
   End Sub

   Protected Sub SetLateDefaults( _
            ByVal objectDef As MapObjectDef, _
            ByVal dataStructure As DbsDataStructure)
      If String.IsNullOrEmpty(objectDef.Schema) Then
         If objectDef.TableName IsNot Nothing Then
            Dim table As DbsTable = dataStructure.GetTable(objectDef.TableName)
            If table Is Nothing Then
               Utility.LogForUser("Child table not found", LogId.CanNotFindChild, objectDef)
            Else
               objectDef.Schema = table.Schema
            End If
         Else
            Dim view As DbsView = dataStructure.GetView(objectDef.ViewName)
            If view IsNot Nothing Then
               objectDef.Schema = view.Schema
            End If
         End If
      End If
   End Sub

   Protected Sub SetMapChildRelationKeyCollectionDefaults( _
            ByVal child As MapChild, _
            ByVal table As DbsTable, _
            ByVal parentObjectDef As MapObjectDef)
      If child.MapRelationKeys Is Nothing OrElse child.MapRelationKeys.Count = 0 Then
         ' Add relation if not specified in ORM
         Dim childTable As DbsTable = table.DbsDataStructures.GetTable(child.TableName)
         Dim parentTable As DbsParentTable = Nothing
         For Each testTable As DbsParentTable In childTable.DbsParentTables
            If testTable.Name.ToLower() = table.Name.ToLower() Then
               parentTable = testTable
               Exit For
            End If
         Next
         If parentTable Is Nothing Then
            Utility.LogForUser("Could not find infer child table", LogId.CanNotFindTable, parentObjectDef, child)
         Else
            SetMapChildRelationKeys(parentObjectDef, child, table, parentTable)
         End If
      End If
   End Sub

   Private Sub SetMapChildRelationKeys( _
            ByVal objectDef As MapObjectDef, _
            ByVal child As MapChild, _
            ByVal table As DbsTable, _
            ByVal childTable As DbsChildTable)
      For i As Int32 = 0 To childTable.DbsChildKeyFields.Count - 1
         Dim parentKey As DbsParentKeyField = Nothing
         Dim childKey As DbsChildKeyField = childTable.DbsChildKeyFields(i)
         If childKey Is Nothing Then
            Throw New System.Exception("Child key field can not be null")
         End If
         Dim ordinal As Nullable(Of Int32) = childKey.Ordinal
         For Each testKey As DbsParentKeyField In childTable.DbsParentKeyFields
            If testKey.Ordinal.Equals(ordinal) Then
               parentKey = testKey
               Exit For
            End If
         Next
         If parentKey Is Nothing Then
            Utility.LogForUser("Could not find parentkey", LogId.CanNotFindKey, objectDef, child, childKey)
         Else
            child.MapRelationKeys.Add(New MapRelationKey(child.MapMappingRoot, _
                     parentKey.Name, childKey.Name, _
                     table.OriginalName, child.TableName, _
                     table.OriginalName, child.TableName, _
                     Nothing, Nothing, _
                     Nothing, Nothing))
         End If
      Next

   End Sub

   Private Sub SetMapChildRelationKeys( _
         ByVal objectDef As MapObjectDef, _
         ByVal child As MapChild, _
         ByVal table As DbsTable, _
         ByVal parentTable As DbsParentTable)
      For i As Int32 = 0 To parentTable.DbsChildFields.Count - 1
         Dim parentKey As DbsParentKeyField = Nothing
         Dim childKey As DbsChildField = parentTable.DbsChildFields(i)
         If childKey Is Nothing Then
            Throw New System.Exception("Child key field can not be null")
         End If
         Dim ordinal As Nullable(Of Int32) = childKey.Ordinal
         For Each testKey As DbsParentKeyField In parentTable.DbsParentKeyFields
            If testKey.Ordinal.Equals(ordinal) Then
               parentKey = testKey
               Exit For
            End If
         Next
         If parentKey Is Nothing Then
            Utility.LogForUser("Could not find parentkey", LogId.CanNotFindKey, objectDef, child, childKey)
         Else
            child.MapRelationKeys.Add(New MapRelationKey(child.MapMappingRoot, _
                     parentKey.Name, childKey.Name, _
                     table.OriginalName, child.TableName, _
                     table.OriginalName, child.TableName, _
                     Nothing, Nothing, _
                     Nothing, Nothing))
         End If
      Next

   End Sub

   Protected Sub SetLateMapChildRelationKeyDefaults( _
            ByVal parent As MapObjectDef, _
            ByVal child As MapChild, _
            ByVal relationKey As MapRelationKey, _
            ByVal table As DbsTable)
      If String.IsNullOrEmpty(relationKey.ParentTable) Then
         relationKey.ParentTable = parent.TableName
      End If
      If String.IsNullOrEmpty(relationKey.ParentObject) Then
         If relationKey.ParentTable = parent.TableName Then
            relationKey.ParentObject = parent.Name
         Else
            relationKey.ParentObject = relationKey.ParentTable
         End If
      End If
      If String.IsNullOrEmpty(relationKey.ParentColumn) Then
         Dim prop As MapProperty = parent.MapProperties.GetProperty(relationKey.ParentProperty)
         If prop Is Nothing Then
            Utility.LogForUser("Parent property could not be found by name", LogId.CanNotFindProperty, parent, child, relationKey)
         Else
            relationKey.ParentColumn = prop.ColumnName
         End If
      End If
      If String.IsNullOrEmpty(relationKey.ParentProperty) Then
         Dim prop As MapProperty = parent.MapProperties.GetPropertyByColumnName(relationKey.ParentTable, relationKey.ParentColumn)
         If prop Is Nothing Then
            prop = parent.MapProperties.GetPropertyByColumnNameMainTable(relationKey.ChildColumn)
         End If
         If prop Is Nothing Then
            ' This is temporarily removed because indirect relations are allowed (the property may not exist here)
            relationKey.ParentProperty = relationKey.ParentColumn
            'Utility.LogForUser("Parent property could not be found by column name", LogId.CanNotFindProperty, parent, child, relationKey)
         Else
            relationKey.ParentProperty = prop.Name
         End If
      End If
      If String.IsNullOrEmpty(relationKey.ChildTable) Then
         relationKey.ChildTable = child.TableName
      End If
      Dim childObjectDef As MapObjectDef = child.MapChildObjectDef
      If childObjectDef Is Nothing AndAlso Not String.IsNullOrEmpty(child.TableName) Then
         childObjectDef = parent.MapMapping.GetObjectDef(child.TableName)
      End If
      If childObjectDef Is Nothing AndAlso Not String.IsNullOrEmpty(child.Ref) Then
         childObjectDef = parent.MapMapping.GetObjectDef(child.Ref)
      End If
      If childObjectDef Is Nothing Then
         Utility.LogForUser("Child objectdef could not be found (2)", LogId.CanNotFindObjectDef, parent, child)
      Else
         If String.IsNullOrEmpty(relationKey.ChildObject) Then
            relationKey.ChildObject = childObjectDef.Name
         End If
         If String.IsNullOrEmpty(relationKey.ChildColumn) Then
            Dim prop As MapProperty = childObjectDef.MapProperties.GetProperty(relationKey.ChildProperty)
            If prop Is Nothing Then
               Utility.LogForUser("Child property could not be found by name", LogId.CanNotFindProperty, parent, child, relationKey)
            Else
               relationKey.ChildColumn = prop.ColumnName
            End If
         End If
         If String.IsNullOrEmpty(relationKey.ChildProperty) Then
            Dim prop As MapProperty = GetChildProperty(child, childObjectDef, relationKey, table.DbsDataStructures)
            If prop Is Nothing Then
               Utility.LogForUser("Child property could not be found by column name", LogId.CanNotFindProperty, parent, child, relationKey)
            Else
               relationKey.ChildProperty = prop.Name
            End If
         End If
      End If
   End Sub

   Private Function GetChildProperty( _
            ByVal child As MapChild, _
            ByVal childObjectDef As MapObjectDef, _
            ByVal relationKey As MapRelationKey, _
            ByVal dataStructures As DbsDataStructureCollection) _
            As MapProperty
      Dim prop As MapProperty = childObjectDef.MapProperties.GetPropertyByColumnName(relationKey.ChildTable, relationKey.ChildColumn)
      If prop Is Nothing Then
         prop = childObjectDef.MapProperties.GetPropertyByColumnNameMainTable(relationKey.ChildColumn)
      End If
      If prop Is Nothing Then
         ' We need to add it as an extra column
         ' Not sure about alias or name here Name should be unique, but I think it is because we just looked for it
         Dim name As String = relationKey.ChildColumn
         Dim table As DbsTable = dataStructures.GetTable(relationKey.ChildTable)
         Dim column As DbsTableColumn = table.DbsTableColumns. _
                  GetTableColumn(relationKey.ChildColumn)
         Dim extraColumn As New MapProperty(child.MapMappingRoot, name, relationKey.ChildColumn, _
                  relationKey.ChildTable, True, True, -1, column.Caption, Nothing, Nothing, Nothing, _
                  Nothing, False, False, column.SQLType, column.NETType, column.NETType, _
                  column.MaxLength, column.Precision, column.Scale, column.IsAutoIncrement, _
                  column.IsPrimaryKey, column.UseForDesc, Nothing, Nothing, Nothing, _
                  column.OriginalName, table.Schema, Utility.GetCasedName(column.Name), _
                  relationKey.ChildObject, Nothing, Nothing, Nothing, Nothing, Nothing)
         'Dim extraColumn As New MapProperty(child.MapMappingRoot, name, relationKey.ChildColumn, _
         '         relationKey.ChildTable, relationKey.ChildObject)
         child.MapExtraColumns.Add(extraColumn)
         prop = extraColumn
      End If
      Return prop
   End Function

   Protected Sub SetLateForeignKeys( _
            ByVal objectDef As MapObjectDef, _
            ByVal dataStructure As DbsDataStructure)
      If objectDef Is Nothing Then
         Throw New System.ArgumentException("ObjectDef can not be nothing")
      End If
      SetMatchingForeignKeys(objectDef)
      For Each foreignKey As MapForeignKey In objectDef.MapForeignKeys
         If String.IsNullOrEmpty(foreignKey.Schema) Then
            Dim fkTable As DbsTable = dataStructure.GetTable(foreignKey.TableName)
            objectDef.Schema = fkTable.Schema
         End If
         For Each key As MapRelationKey In foreignKey.MapRelationKeys
            SetLateForeignKeyRelationKeyDefaults(objectDef, foreignKey, key)
         Next
      Next
   End Sub

   Private Sub SetMatchingForeignKeys(ByVal objectDef As MapObjectDef)
      ' I seem to have gone around a bit as to whether to include this logic. 
      ' Should we force the child/fkeys to match. If they don't Child data 
      ' assignments get ugly.
      For Each child As MapChild In objectDef.MapChildren
         Dim childObjectDef As MapObjectDef = objectDef.MapMapping.GetObjectDef(child.ObjectName)
         If childObjectDef Is Nothing Then
            Utility.LogForUser("ObjectDef not found", LogId.CanNotFindObjectDef)
            Continue For
         End If
         Dim found As Boolean
         For Each fk As MapForeignKey In childObjectDef.MapForeignKeys
            If fk.MapParentObjectDef Is objectDef Then
               found = True
            End If
         Next
         If Not found Then
            Dim fk As New MapForeignKey(objectDef.MapMappingRoot, objectDef.Name, objectDef.TableName, objectDef.Schema)
            childObjectDef.MapForeignKeys.Add(fk)
            fk.MapChild = child
            fk.MapParentObjectDef = objectDef
            For Each childKey As MapRelationKey In child.MapRelationKeys
               fk.MapRelationKeys.Add(New MapRelationKey(objectDef.MapMappingRoot, _
                         childKey.ParentColumn, childKey.ChildColumn, childKey.ParentTable, _
                         childKey.ChildTable, childKey.ParentAlias, childKey.ChildAlias, _
                         childKey.ParentObject, childKey.ChildObject, childKey.ParentProperty, _
                         childKey.ChildProperty))
            Next
         End If
      Next
   End Sub

   Protected Sub SetLateForeignKeyRelationKeyDefaults( _
         ByVal childObjectDef As MapObjectDef, _
         ByVal foreignKey As MapForeignKey, _
         ByVal relationKey As MapRelationKey)
      If String.IsNullOrEmpty(relationKey.ChildObject) Then
         If childObjectDef Is Nothing Then
            relationKey.ChildObject = relationKey.ChildTable
         Else
            relationKey.ChildObject = childObjectDef.Name
         End If
      End If
      If childObjectDef Is Nothing Then
         childObjectDef = foreignKey.MapMappingRoot.GetByObjectName(relationKey.ParentObject)
         If childObjectDef Is Nothing Then
            Utility.LogForUser("Can not find child object def", LogId.CanNotFindObjectDef, childObjectDef, relationKey)
         End If
      End If
      If String.IsNullOrEmpty(relationKey.ChildProperty) Then
         Dim prop As MapProperty = childObjectDef.MapProperties.GetPropertyByColumnName(relationKey.ChildTable, relationKey.ChildColumn)
         If prop Is Nothing Then
            prop = childObjectDef.MapProperties.GetPropertyByColumnNameMainTable(relationKey.ChildColumn)
         End If
         If prop Is Nothing Then
            Utility.LogForUser(String.Format("Can not find property for child column for {0}", relationKey.ParentColumn), LogId.CanNotFindProperty, childObjectDef, relationKey)
            relationKey.ChildProperty = relationKey.ChildColumn
         Else
            relationKey.ChildProperty = prop.Name
         End If
      End If

      If String.IsNullOrEmpty(relationKey.ParentObject) Then
         relationKey.ParentObject = relationKey.ParentTable
      End If
      Dim parentObjectDef As MapObjectDef = childObjectDef.MapMappingRoot.GetByObjectName(relationKey.ParentObject)
      If parentObjectDef Is Nothing Then
         Utility.LogForUser("Can not find parent object def", LogId.CanNotFindObjectDef, childObjectDef, relationKey)
      End If
      If String.IsNullOrEmpty(relationKey.ParentProperty) And _
               Not String.IsNullOrEmpty(relationKey.ParentObject) Then
         Dim prop As MapProperty = parentObjectDef.MapProperties.GetPropertyByColumnName(relationKey.ParentTable, relationKey.ParentColumn)
         If prop Is Nothing Then
            Utility.LogForUser(String.Format("Can not find property for parent column for {0})", relationKey.ParentColumn), LogId.CanNotFindProperty, childObjectDef, relationKey)
            relationKey.ParentProperty = relationKey.ParentColumn
         Else
            relationKey.ParentProperty = prop.Name
         End If
      End If
   End Sub

   Protected Sub SetMapForeignkeyCollectionDefaults( _
         ByVal objectdef As MapObjectDef, _
         ByVal foreignKeys As MapForeignKeyCollection, _
         ByVal table As DbsTable)
      If foreignKeys.Count = 0 Then
         AddForeignKey(objectdef, table)
         'For Each dbParent As DbsParentTable In table.DbsParentTables
         '   'Dim parentObjectDef As MapObjectDef = _
         '   '         objectdef.MapMapping.MapObjectDefs.GetMainByTableName _
         '   '         (dbParent.Name, table.DbsDataStructures(0))
         '   Dim parentObjectDef As MapObjectDef = _
         '            objectdef.MapMapping.MapObjectDefs.GetBestByTableNameAndChild _
         '            (dbParent.Name, table.Name, dbParent.DbsDataStructures)
         '   If parentObjectDef Is Nothing Then
         '      parentObjectDef = objectdef.MapMapping.MapObjectDefs.GetBestByTableName _
         '            (dbParent.Name, dbParent.DbsDataStructures)
         '   End If
         '   If parentObjectDef Is Nothing Then
         '      Utility.LogForUser("Could not find parent objectdef")
         '   End If
         '   Dim child As MapChild = parentObjectDef.MapChildren.GetChildByChildObjectDef(objectdef)
         '   Dim newFKey As New MapForeignKey(objectdef.MapMappingRoot, _
         '            parentObjectDef.Name, parentObjectDef.TableName, _
         '            parentObjectDef.Schema)
         '   newFKey.MapParentObjectDef = parentObjectDef
         '   newFKey.MapChild = child
         '   objectdef.MapForeignKeys.Add(newFKey)
         'Next
         '' Finding foreign keys fom parents is invalid.
         ''For Each parentObjectDef As MapObjectDef In objectdef.MapMapping.MapObjectDefs
         ''   For Each child As MapChild In parentObjectDef.MapChildren
         ''      If child.MapChildObjectDef Is objectdef Then
         ''         Dim newForeignKey As New MapForeignKey(objectdef.MapMappingRoot, _
         ''                   parentObjectDef.Name, parentObjectDef.TableName, parentObjectDef.Schema)
         ''         newForeignKey.MapParentObjectDef = parentObjectDef
         ''         newForeignKey.MapChild = child
         ''         objectdef.MapForeignKeys.Add(newForeignKey)
         ''      End If
         ''   Next
         ''Next
      End If
   End Sub

   Private Sub AddForeignKey(ByVal objectDef As MapObjectDef, ByVal table As DbsTable)
      For Each dbParent As DbsParentTable In table.DbsParentTables
         'Dim parentObjectDef As MapObjectDef = _
         '         objectdef.MapMapping.MapObjectDefs.GetMainByTableName _
         '         (dbParent.Name, table.DbsDataStructures(0))
         Dim parentObjectDef As MapObjectDef = _
                  objectDef.MapMapping.MapObjectDefs.GetBestByTableNameAndChild _
                  (dbParent.Name, table.Name, dbParent.DbsDataStructures)
         If parentObjectDef Is Nothing Then
            parentObjectDef = objectDef.MapMapping.MapObjectDefs.GetBestByTableName _
                  (dbParent.Name, dbParent.DbsDataStructures)
         End If
         If parentObjectDef Is Nothing Then
            Utility.LogForUser("Could not find parent objectdef")
         End If
         Dim alreadyExists As Boolean = False
         For Each existingFKey As MapForeignKey In objectDef.MapForeignKeys
            If existingFKey.Name = parentObjectDef.Name Then
               alreadyExists = True
            End If
         Next
         If Not alreadyExists Then
            Dim child As MapChild = parentObjectDef.MapChildren.GetChildByChildObjectDef(objectDef)
            Dim newFKey As New MapForeignKey(objectDef.MapMappingRoot, _
                     parentObjectDef.Name, parentObjectDef.TableName, _
                     parentObjectDef.Schema)
            newFKey.MapParentObjectDef = parentObjectDef
            newFKey.MapChild = child
            objectDef.MapForeignKeys.Add(newFKey)
         End If
      Next
   End Sub

   Protected Sub SetMapForeignkeyDefaults(ByVal foreignKey As MapForeignKey, ByVal table As DbsTable)
   End Sub

   ''' <summary>
   ''' 
   ''' </summary>
   ''' <param name="objectDef"></param>
   ''' <param name="foreignkey"></param>
   ''' <param name="relationKeys"></param>
   ''' <param name="table"></param>
   ''' <remarks>
   ''' We can't do this in the SetMapForeignKeyCollectionDefaults method because
   ''' we may also have to manage FKeys defined in the ORM file, maybe
   ''' <para/>
   ''' 20070726 KAD I am changing some things around lookup tables. They will 
   ''' now have children in the map file, and maybe in the SPInput, but they can
   ''' be blocked at the GenInput level with the new blocking mechanism I am 
   ''' going to put in place.
   ''' </remarks>
   Protected Sub SetMapForeignRelationKeyCollectionDefaults( _
         ByVal objectDef As MapObjectDef, _
         ByVal foreignkey As MapForeignKey, _
         ByVal relationKeys As MapRelationKeyCollection, _
         ByVal table As DbsTable)
      ' KAD 20071002 When I changed the basic foreignkey gathering back to the database I am not sure this remains valid
      If foreignkey.MapParentObjectDef Is Nothing Or foreignkey.MapChild Is Nothing Then
         'AddForeignKey(objectDef, table)
         ''For Each parentObjectDef As MapObjectDef In objectDef.MapMapping.MapObjectDefs
         ''   The problem is that we must repeat the check for child here because the 
         ''   child may be a forward ref. We need to stealthe code near line 117 by 
         ''   moving it into a couple of functions
         ''   For Each child As MapChild In parentObjectDef.MapChildren
         ''      If foreignkey.MapParentObjectDef Is Nothing Then
         ''         foreignkey.MapParentObjectDef = parentObjectDef
         ''      End If
         ''      If foreignkey.MapChild Is Nothing Then
         ''         foreignkey.MapChild = child
         ''      End If
         ''   Next
         ''Next
      End If

      ' To clone or ref? CLone felt safer, but missed later updates to the property and object names
      If foreignkey.MapChild Is Nothing Then
         Dim parentTable As DbsParentTable = table.DbsParentTables(foreignkey.TableName)
         For i As Int32 = 0 To parentTable.DbsChildFields.Count - 1
            Dim parentKey As DbsParentKeyField = parentTable.DbsParentKeyFields(i)
            Dim childKey As DbsChildField = parentTable.DbsChildFields(i)
            Dim newMapRelationKey As New MapRelationKey(objectDef.MapMappingRoot, _
                     parentKey.Name, childKey.Name, _
                     table.OriginalName, objectDef.TableName, _
                     table.OriginalName, objectDef.TableName, _
                     Nothing, Nothing, _
                     Nothing, Nothing)
            relationKeys.Add(newMapRelationKey)
         Next
      Else
         For Each key As MapRelationKey In foreignkey.MapChild.MapRelationKeys
            relationKeys.Add(key)
         Next
      End If
   End Sub


   'Protected Sub SetMapForeignkeyCollectionDefaults( _
   '         ByVal objectdef As MapObjectDef, _
   '         ByVal foreignKeys As MapForeignKeyCollection, _
   '         ByVal table As DbsTable)
   '   If foreignKeys.Count = 0 Then
   '      Dim existingParents As New List(Of String)
   '      ' Retrive foreign keys from datastructure
   '      For Each parentTable As DbsParentTable In table.DbsParentTables
   '         Dim isOk As Boolean = True
   '         Dim parentId As String = parentTable.Name
   '         For i As Int32 = 0 To parentTable.DbsParentKeyFields.Count - 1
   '            parentId &= "|" & parentTable.DbsParentKeyFields(i).Name
   '         Next
   '         If existingParents.Contains(parentId) Then
   '            Continue For
   '         End If
   '         existingParents.Add(parentId)
   '         If String.Compare(table.OriginalName, parentTable.Name, StringComparison.InvariantCultureIgnoreCase) = 0 Then
   '            ' Check that relations are different
   '            isOk = False
   '            For i As Int32 = 0 To parentTable.DbsParentKeyFields.Count - 1
   '               If parentTable.DbsChildFields(i).Name <> parentTable.DbsParentKeyFields(i).Name Then
   '                  isOk = True
   '                  Exit For
   '               End If
   '            Next
   '         End If
   '         If isOk Then
   '            Dim parentKeyList As New List(Of DbsParentKeyField)
   '            Dim childKeyList As New List(Of DbsChildField)
   '            ' Dim foreignKeyTable As New BuildForeignKeyTable(parentTable.Name)
   '            For Each parentkey As DbsParentKeyField In parentTable.DbsParentKeyFields
   '               Dim childField As DbsChildField = Nothing
   '               For Each testKey As DbsChildField In parentTable.DbsChildFields
   '                  If testKey.Ordinal.Equals(parentkey.Ordinal) Then
   '                     childField = testKey
   '                  End If
   '               Next
   '               If childField Is Nothing Then
   '                  Utility.LogForUser("Child Field not found", LogId.CanNotFindField, objectdef, parentTable, parentkey)
   '               Else
   '                  parentKeyList.Add(parentkey)
   '                  childKeyList.Add(childField)
   '               End If
   '            Next
   '            If parentKeyList.Count > 0 Then
   '               ' In some weird cases with multiple object defs, this could be a problem. These will have to be manually defined I think. 
   '               Dim foreignObjectDef As MapObjectDef = objectdef.MapMappingRoot.GetByTableName(parentTable.Name)(0)
   '               Dim newForeignKey As New MapForeignKey(objectdef.MapMappingRoot, _
   '                        foreignObjectDef.Name, parentTable.Name, Nothing)
   '               For i As Int32 = 0 To parentKeyList.Count - 1
   '                  If childKeyList(i) Is Nothing Then
   '                     Utility.LogForUser("Child Field not found (2)", LogId.CanNotFindField, objectdef, parentTable, parentKeyList(i))
   '                  Else
   '                     AddRelationKey(parentTable, table, newForeignKey, parentKeyList(i), childKeyList(i))
   '                  End If
   '                  'Dim parentKey As DbsParentKeyField = parentKeyList(i)
   '                  'Dim childKey As DbsChildField = childKeyList(i)
   '                  'Dim parentObjectDef As MapObjectDef = objectdef.MapMappingRoot.GetByTableName(parentTable.Name)(0)
   '                  'Dim childObjectDef As MapObjectDef = objectdef.MapMappingRoot.GetByTableName(table.Name)(0)
   '                  'newForeignKey.MapRelationKeys.Add(New MapRelationKey(objectdef.MapMappingRoot, parentTable.Name, table.Name, _
   '                  '         parentTable.Name, table.Name, parentKey.Name, childKey.Name, parentObjectDef.Name, childObjectDef.Name, _
   '                  '         parentKey.Name, childKey.Name))
   '               Next
   '               foreignKeys.Add(newForeignKey)
   '            End If
   '         End If
   '      Next
   '   End If
   'End Sub
   'Protected Sub SetMapForeignkeyDefaults(ByVal foreignKey As MapForeignKey, ByVal table As DbsTable)
   'End Sub

   'Protected Sub SetMapForeignRelationKeyCollectionDefaults( _
   '         ByVal objectDef As MapObjectDef, _
   '         ByVal foreignkey As MapForeignKey, _
   '         ByVal relationKeys As MapRelationKeyCollection, _
   '         ByVal table As DbsTable)
   '   ' This is used when the ORM file defines the relationship, but not the keys.
   '   If relationKeys.Count = 0 Then
   '      Dim parenttable As DbsParentTable = Nothing
   '      For Each testTable As DbsParentTable In table.DbsParentTables
   '         If testTable.Name = foreignkey.TableName Then
   '            parenttable = testTable
   '            Exit For
   '         End If
   '      Next
   '      If parenttable Is Nothing Then
   '         Utility.LogForUser("Parent Table not found", LogId.CanNotFindTable, objectDef, foreignkey)
   '      Else
   '         For Each parentKey As DbsParentKeyField In parenttable.DbsParentKeyFields
   '            Dim childField As DbsChildField = Nothing
   '            For Each testKey As DbsChildField In parenttable.DbsChildFields
   '               If testKey.Ordinal.Equals(parentKey.Ordinal) Then
   '                  childField = testKey
   '                  Exit For
   '               End If
   '            Next
   '            If childField Is Nothing Then
   '               Utility.LogForUser("Child Field not found (3)", LogId.CanNotFindField, objectDef, parenttable, parentKey)
   '            Else
   '               AddRelationKey(parenttable, table, foreignkey, parentKey, childField)
   '            End If
   '            'If childkey Is Nothing Then
   '            '   ' TODO: Figure out if this is an error
   '            'Else
   '            '   Dim parentObjectDef As MapObjectDef = foreignkey.MapMappingRoot.GetByTableName(parenttable.Name)(0)
   '            '   Dim childObjectDef As MapObjectDef = foreignkey.MapMappingRoot.GetByTableName(table.Name)(0)
   '            '   relationKeys.Add(New MapRelationKey(foreignkey.MapMappingRoot, foreignkey.TableName, table.Name, _
   '            '            foreignkey.TableName, table.Name, parentKey.Name, childkey.Name, parentObjectDef.Name, childObjectDef.Name, _
   '            '            parentKey.Name, childkey.Name))
   '            'End If
   '         Next
   '      End If
   '   End If
   'End Sub

   Private Sub AddRelationKey( _
            ByVal parentTable As DbsParentTable, _
            ByVal childTable As DbsTable, _
            ByVal foreignKey As MapForeignKey, _
            ByVal parentKey As DbsParentKeyField, _
            ByVal childField As DbsChildField)
      If childField Is Nothing Then
         Throw New System.ArgumentException("Child field can not be null")
      Else
         Dim parentObjectDefs As MapObjectDefCollection = foreignKey.MapMappingRoot.GetByTableName(parentTable.Name)
         ' Which one to use is an active question. Currently its the first one where this child is valid
         Dim parentObjectDef As MapObjectDef = Nothing
         For Each testParent As MapObjectDef In parentObjectDefs
            For Each child As MapChild In testParent.MapChildren
               If child.TableName = childTable.OriginalName Then
                  parentObjectDef = testParent
                  Exit For
               End If
            Next
         Next
         Dim childObjectDef As MapObjectDef = foreignKey.MapMappingRoot.GetByTableName(childTable.OriginalName)(0)
         Dim parentProp As MapProperty = parentObjectDef.GetPropertyByColumnName(parentKey.Name)
         Dim childProp As MapProperty = childObjectDef.GetPropertyByColumnName(childField.Name)
         ' TODO: Tell user if either objectDef or property is null
         foreignKey.MapRelationKeys.Add(New MapRelationKey(foreignKey.MapMappingRoot, _
                  parentKey.Name, childField.Name, _
                  foreignKey.TableName, childTable.OriginalName, _
                  foreignKey.TableName, childTable.OriginalName, _
                  parentObjectDef.Name, childObjectDef.Name, _
                  Nothing, Nothing))
      End If
   End Sub

   Protected Sub SetMapForeignRelationKeyDefaults(ByVal relationKeys As MapRelationKey, ByVal table As DbsTable)

   End Sub

   Protected Sub SetMapJoinBaseCollectionDefaults(ByVal objectdef As MapObjectDef, ByVal joins As MapJoinBaseCollection, ByVal table As DbsTable)
      ' We don't default any joins at present
   End Sub
   'Protected Sub SetMapJoinBaseDefaults( _
   '         ByVal join As MapJoinBase, _
   '         ByVal table As DbsTable, _
   '         ByVal datastructure As DbsDataStructure)
   '   If join IsNot Nothing Then
   '      If String.IsNullOrEmpty(join.Name) Then
   '         join.Name = join.TableName
   '      End If
   '      If String.IsNullOrEmpty(join.TableName) Then
   '         join.TableName = join.Name
   '      End If
   '      Dim joinTable As DbsTable = datastructure.DbsTables.GetTable(join.TableName, True, True)
   '      If joinTable IsNot Nothing Then
   '         join.TableName = joinTable.Name
   '         Dim parentTable As DbsParentTable = table.DbsParentTables(join.TableName)
   '         If String.IsNullOrEmpty(join.Alias) Then
   '            join.Alias = join.TableName
   '         End If
   '         If String.IsNullOrEmpty(join.Clause) Then
   '            ' Do we default this clause?
   '         End If
   '         If String.IsNullOrEmpty(join.JoinTo) Then
   '            ' Do not default, this let's you joi
   '         End If
   '         If String.IsNullOrEmpty(join.JoinType) Then
   '            join.JoinType = "INNER"
   '         End If
   '         If String.IsNullOrEmpty(join.LeftAlias) Then
   '            join.LeftAlias = table.Name
   '         End If
   '         If String.IsNullOrEmpty(join.LeftOriginalName) Then
   '            join.LeftOriginalName = table.OriginalName
   '         End If
   '         ' Don't default NoColumns
   '         If String.IsNullOrEmpty(join.RightOriginalName) Then
   '            join.RightOriginalName = joinTable.OriginalName
   '         End If
   '      End If
   '   End If
   'End Sub

   Protected Sub SetMapJoinCollectionDefaults( _
         ByVal joins As IMapJoinCollection, _
         ByVal table As DbsTable, _
         ByVal datastructure As DbsDataStructure)
      For Each join As IMapJoin In joins
         If join IsNot Nothing Then
            If String.IsNullOrEmpty(join.Name) Then
               join.Name = join.TableName
            End If
            If String.IsNullOrEmpty(join.TableName) Then
               join.TableName = join.Name
            End If
            Dim joinTable As DbsTable = datastructure.DbsTables.GetTable(join.TableName, True, True)
            If joinTable IsNot Nothing Then
               join.TableName = joinTable.OriginalName
               Dim parentTable As DbsParentTable = table.DbsParentTables(join.TableName)
               If String.IsNullOrEmpty(join.Alias) Then
                  ' The alias is fixed later in the default creation
                  join.Alias = join.TableName
               End If
               If String.IsNullOrEmpty(join.Clause) Then
                  ' Do we default this clause?
               End If
               If String.IsNullOrEmpty(join.JoinTo) Then
                  ' Do not default, this let's you joi
               End If
               If String.IsNullOrEmpty(join.JoinType) Then
                  join.JoinType = "INNER"
               End If
               If String.IsNullOrEmpty(join.LeftAlias) Then
                  join.LeftAlias = table.Name
               End If
               If String.IsNullOrEmpty(join.LeftOriginalName) Then
                  join.LeftOriginalName = table.OriginalName
               End If
               ' Don't default NoColumns
               If String.IsNullOrEmpty(join.RightOriginalName) Then
                  join.RightOriginalName = joinTable.OriginalName
               End If
            End If
         End If
         SetMapJoinKeyCollectionDefaults(join.MapJoinKeys, join, table)
         For Each joinKey As MapJoinKey In join.MapJoinKeys
            SetMapJoinKeyDefaults(joinKey, join, table, datastructure)
         Next
         SetMapJoinColumnCollectionDefaults(join.MapJoinInColumns, join, table, datastructure)
         For Each joinColumn As MapJoinInColumn In join.MapJoinInColumns
            SetMapJoinColumnDefaults(joinColumn, join, table, datastructure)
         Next
      Next
   End Sub


   Protected Sub SetMapJoinInCollectionDefaults(ByVal objectdef As MapObjectDef, ByVal joins As MapJoinInCollection, ByVal table As DbsTable)
      ' We don't default any joins at present
   End Sub
   'Protected Sub SetMapJoinInDefaults( _
   '         ByVal join As MapJoinIn, _
   '         ByVal table As DbsTable, _
   '         ByVal datastructure As DbsDataStructure)
   '   If join IsNot Nothing Then
   '      If String.IsNullOrEmpty(join.Name) Then
   '         join.Name = join.TableName
   '      End If
   '      If String.IsNullOrEmpty(join.TableName) Then
   '         join.TableName = join.Name
   '      End If
   '      Dim joinTable As DbsTable = datastructure.DbsTables.GetTable(join.TableName, True, True)
   '      If joinTable IsNot Nothing Then
   '         join.TableName = joinTable.Name
   '         Dim parentTable As DbsParentTable = table.DbsParentTables(join.TableName)
   '         If String.IsNullOrEmpty(join.Alias) Then
   '            join.Alias = join.TableName
   '         End If
   '         If String.IsNullOrEmpty(join.Clause) Then
   '            ' Do we default this clause?
   '         End If
   '         If String.IsNullOrEmpty(join.JoinTo) Then
   '            ' Do not default, this let's you joi
   '         End If
   '         If String.IsNullOrEmpty(join.JoinType) Then
   '            join.JoinType = "INNER"
   '         End If
   '         If String.IsNullOrEmpty(join.LeftAlias) Then
   '            join.LeftAlias = table.Name
   '         End If
   '         If String.IsNullOrEmpty(join.LeftOriginalName) Then
   '            join.LeftOriginalName = table.OriginalName
   '         End If
   '         ' Don't default NoColumns
   '         If String.IsNullOrEmpty(join.RightOriginalName) Then
   '            join.RightOriginalName = joinTable.OriginalName
   '         End If
   '      End If
   '   End If
   'End Sub

   'Protected Sub SetMapJoinBaseKeyCollectionDefaults( _
   '            ByVal joinKeys As MapJoinKeyCollection, _
   '            ByVal joinbase As MapJoinBase, _
   '            ByVal table As DbsTable)
   '   If joinKeys.Count = 0 AndAlso Not String.IsNullOrEmpty(joinbase.Name) Then
   '      ' Assume join is to a parent
   '      Dim parentTable As DbsParentTable = table.DbsParentTables(joinbase.TableName)
   '      For Each parentKey As DbsParentKeyField In parentTable.DbsParentKeyFields
   '         Dim childKey As DbsChildField = Nothing
   '         For Each testKey As DbsChildField In parentTable.DbsChildFields
   '            If testKey.Ordinal = parentKey.Ordinal Then
   '               childKey = testKey
   '               Exit For
   '            End If
   '         Next
   '         joinKeys.Add(New MapJoinKey(joinbase.MapMappingRoot, parentKey.Name, childKey.Name))
   '      Next
   '   End If
   'End Sub

   Protected Sub SetMapJoinKeyCollectionDefaults( _
               ByVal joinKeys As MapJoinKeyCollection, _
               ByVal join As IMapJoin, _
               ByVal table As DbsTable)
      If joinKeys.Count = 0 AndAlso Not String.IsNullOrEmpty(join.TableName) Then
         ' Assume join is to a parent
         Dim parentTable As DbsParentTable = table.DbsParentTables(join.TableName)
         If parentTable Is Nothing Then
            Utility.LogForUser("Parent table not found. Relationship may be missing", LogId.CanNotFindParent, TryCast(join, WrapperBase))
         End If
         If parentTable IsNot Nothing Then
            For Each parentKey As DbsParentKeyField In parentTable.DbsParentKeyFields
               Dim childKey As DbsChildField = Nothing
               For Each testKey As DbsChildField In parentTable.DbsChildFields
                  If testKey.Ordinal.Equals(parentKey.Ordinal) Then
                     childKey = testKey
                     Exit For
                  End If
               Next
               joinKeys.Add(New MapJoinKey(join.MapMappingRoot, childKey.Name, parentKey.Name, Nothing, Nothing, Nothing, Nothing))
            Next
         End If
      End If
   End Sub

   Protected Sub SetMapJoinKeyDefaults( _
               ByVal joinKey As MapJoinKey, _
               ByVal join As IMapJoin, _
               ByVal table As DbsTable, _
               ByVal datastructure As DbsDataStructure)
   End Sub

   'Protected Sub SetMapJoinBaseColumnCollectionDefaults(ByVal joinColumns As MapJoinInColumnCollection, _
   '                      ByVal joinbase As MapJoinBase, ByVal table As DbsTable, _
   '                      ByVal datastructure As DbsDataStructure)
   '   If joinColumns.Count = 0 AndAlso Not String.IsNullOrEmpty(joinbase.Name) Then
   '      ' Then bring in all the columns from the other table
   '      Dim joinTableName As String = joinbase.TableName
   '      Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
   '      For Each column As DbsTableColumn In joinTable.DbsTableColumns
   '         joinColumns.Add(New MapJoinInColumn(joinbase.MapMappingRoot, column.Name, Nothing, Nothing, Nothing))
   '      Next
   '   End If
   'End Sub
   'Protected Sub SetMapJoinBaseColumnDefaults(ByVal joinColumn As MapJoinInColumn, ByVal joinbase As MapJoinBase, _
   '               ByVal table As DbsTable, ByVal datastructure As DbsDataStructure)
   '   Dim joinTableName As String = joinbase.TableName
   '   Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
   '   If String.IsNullOrEmpty(joinColumn.ColumnName) Then
   '      joinColumn.ColumnName = joinColumn.Name
   '   End If
   '   Dim tableColumn As DbsTableColumn = joinTable.DbsTableColumns(joinColumn.ColumnName)
   '   If String.IsNullOrEmpty(joinColumn.Alias) Then
   '      joinColumn.Alias = joinColumn.ColumnName
   '   End If
   '   If String.IsNullOrEmpty(joinColumn.Caption) Then
   '      joinColumn.Caption = tableColumn.Caption
   '   End If
   'End Sub

   'Protected Sub SetMapJoinBaseColumnDefaults(ByVal joinColumn As MapJoinInColumn, ByVal joinbase As MapJoinBase, _
   '               ByVal table As DbsTable, ByVal datastructure As DbsDataStructure)
   '   Dim joinTableName As String = joinbase.TableName
   '   Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
   '   If String.IsNullOrEmpty(joinColumn.ColumnName) Then
   '      joinColumn.ColumnName = joinColumn.Name
   '   End If
   '   Dim tableColumn As DbsTableColumn = joinTable.DbsTableColumns(joinColumn.ColumnName)
   '   If String.IsNullOrEmpty(joinColumn.Alias) Then
   '      joinColumn.Alias = joinColumn.ColumnName
   '   End If
   '   If String.IsNullOrEmpty(joinColumn.Caption) Then
   '      joinColumn.Caption = tableColumn.Caption
   '   End If
   'End Sub


   Protected Sub SetMapJoinColumnCollectionDefaults( _
               ByVal joinColumns As MapJoinInColumnCollection, _
               ByVal join As IMapJoin, _
               ByVal table As DbsTable, _
               ByVal datastructure As DbsDataStructure)
      If joinColumns.Count = 0 AndAlso Not String.IsNullOrEmpty(join.Name) Then
         ' Then bring in all the columns from the other table
         Dim joinTableName As String = join.TableName
         Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
         For Each column As DbsTableColumn In joinTable.DbsTableColumns
            joinColumns.Add(New MapJoinInColumn(join.MapMappingRoot, _
                  column.Name, column.OriginalName, Nothing, Nothing))
         Next
      End If
   End Sub
   Protected Sub SetMapJoinColumnDefaults( _
               ByVal joinColumn As MapJoinInColumn, _
               ByVal join As IMapJoin, _
               ByVal table As DbsTable, _
               ByVal datastructure As DbsDataStructure)
      Dim joinTableName As String = join.TableName
      Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
      If String.IsNullOrEmpty(joinColumn.ColumnName) Then
         joinColumn.ColumnName = joinColumn.Name
      End If
      Dim tableColumn As DbsTableColumn = joinTable.DbsTableColumns(joinColumn.ColumnName)
      If String.IsNullOrEmpty(joinColumn.Alias) Then
         joinColumn.Alias = joinColumn.ColumnName
      End If
      If String.IsNullOrEmpty(joinColumn.Caption) And tableColumn IsNot Nothing Then
         joinColumn.Caption = tableColumn.Caption
      End If
   End Sub

   '   Protected Sub AddJoinColumns(ByVal objectDef As MapObjectDef, ByVal dbsDataStructure As DbsDataStructure)
   '      Dim ordinal As Int32 = objectDef.MapProperties.Count
   '      For Each join As MapJoinIn In objectDef.MapJoinIns
   '         Dim table As DbsTable = dbsDataStructure.GetTable(join.TableName)
   '         If table Is Nothing Then
   '            Utility.LogForUser("Can't find join table", LogId.CanNotFindTable, objectDef, join)
   '         End If
   '         For Each joinColumn As MapJoinInColumn In join.MapJoinInColumns
   '            Dim column As DbsTableColumn = table.DbsTableColumns.GetTableColumn(joinColumn.ColumnName)
   '            If column Is Nothing Then
   '               Utility.LogForUser("Can't find join column", LogId.CanNotFindTable, objectDef, join, joinColumn)
   '            End If
   'dim prop as New MapProperty(objectdef.MapMappingRoot, joinColumn.Name, joinColumn.ColumnName, join.TableName,  _
   '   true, true, ordinal, joinColumn.Caption, column.Default, 
   '            ordinal += 1
   '         Next
   '      Next
   '      For Each join As MapJoinBase In objectDef.MapJoinBases

   '      Next
   '   End Sub

   'Protected Sub SetMapJoinInKeyCollectionDefaults(ByVal joinKeys As MapJoinKeyCollection, _
   '                    ByVal joinin As MapJoinIn, ByVal table As DbsTable)
   '   If joinKeys.Count = 0 AndAlso Not String.IsNullOrEmpty(joinin.Name) Then
   '      ' Assume join is to a parent
   '      Dim parentTable As DbsParentTable = table.DbsParentTables(joinin.TableName)
   '      For Each parentKey As DbsParentKeyField In parentTable.DbsParentKeyFields
   '         Dim childKey As DbsChildField = Nothing
   '         For Each testKey As DbsChildField In parentTable.DbsChildFields
   '            If testKey.Ordinal = parentKey.Ordinal Then
   '               childKey = testKey
   '               Exit For
   '            End If
   '         Next
   '         joinKeys.Add(New MapJoinKey(joinin.MapMappingRoot, childKey.Name, parentKey.Name))
   '      Next
   '   End If
   'End Sub

   Protected Sub SetMapJoinInColumnCollectionDefaults(ByVal joinColumns As MapJoinInColumnCollection, _
                        ByVal joinin As MapJoinIn, ByVal table As DbsTable, _
                        ByVal datastructure As DbsDataStructure)
      If joinColumns.Count = 0 AndAlso Not String.IsNullOrEmpty(joinin.Name) Then
         ' Then bring in all the columns from the other table
         Dim joinTableName As String = joinin.TableName
         Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
         For Each column As DbsTableColumn In joinTable.DbsTableColumns
            joinColumns.Add(New MapJoinInColumn(joinin.MapMappingRoot, Nothing, column.Name, Nothing, Nothing))
         Next
      End If
   End Sub
   Protected Sub SetMapJoinInColumnDefaults(ByVal joinColumn As MapJoinInColumn, ByVal joinin As MapJoinIn, _
                        ByVal table As DbsTable, ByVal datastructure As DbsDataStructure)
      Dim joinTableName As String = joinin.TableName
      Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
      If String.IsNullOrEmpty(joinColumn.ColumnName) Then
         joinColumn.ColumnName = joinColumn.Name
      End If
      Dim tableColumn As DbsTableColumn = joinTable.DbsTableColumns(joinColumn.ColumnName)
      If String.IsNullOrEmpty(joinColumn.Alias) Then
         joinColumn.Alias = joinColumn.ColumnName
      End If
      If String.IsNullOrEmpty(joinColumn.Caption) Then
         joinColumn.Caption = tableColumn.Caption
      End If
   End Sub

   Protected Sub SetMapJoinBaseColumnCollectionDefaults(ByVal joinColumns As MapJoinInColumnCollection, _
                          ByVal joinin As MapJoinIn, ByVal table As DbsTable, _
                          ByVal datastructure As DbsDataStructure)
      If joinColumns.Count = 0 Then
         ' Then bring in all the columns from the other table
         Dim joinTableName As String = joinin.TableName
         Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
         For Each column As DbsTableColumn In joinTable.DbsTableColumns
            joinColumns.Add(New MapJoinInColumn(joinin.MapMappingRoot, Nothing, column.Name, Nothing, Nothing))
         Next
      End If
   End Sub
   Protected Sub MapJoinBaseColumnDefaults(ByVal joinColumn As MapJoinInColumn, ByVal joinin As MapJoinIn, _
                        ByVal table As DbsTable, ByVal datastructure As DbsDataStructure)
      Dim joinTableName As String = joinin.TableName
      Dim joinTable As DbsTable = datastructure.DbsTables(joinTableName)
      If String.IsNullOrEmpty(joinColumn.ColumnName) Then
         joinColumn.ColumnName = joinColumn.Name
      End If
      Dim tableColumn As DbsTableColumn = joinTable.DbsTableColumns(joinColumn.ColumnName)
      If String.IsNullOrEmpty(joinColumn.Alias) Then
         joinColumn.Alias = joinColumn.ColumnName
      End If
      If String.IsNullOrEmpty(joinColumn.Caption) Then
         joinColumn.Alias = tableColumn.Caption
      End If
   End Sub

   Protected Sub SetMapPrivilegeCollectionDefaults( _
            ByVal objectdef As MapObjectDef, _
            ByVal privileges As MapPrivilegeCollection, _
            ByVal viewOrTable As IViewOrTable)
      For Each rootPrivilege As MapPrivilege In objectdef.MapMapping.MapDefaultPrivileges
         Dim found As Boolean = False
         For Each privilege As MapPrivilege In privileges
            If privilege.Grantee = rootPrivilege.Grantee Then
               found = True
            End If
         Next
         If Not found Then
            objectdef.MapObjectPrivileges.Add(New MapPrivilege( _
                     objectdef.MapMappingRoot, rootPrivilege.Grantee, _
                     rootPrivilege.Rights, rootPrivilege.Visible, rootPrivilege.Insert, _
                     rootPrivilege.Edit, rootPrivilege.Delete, rootPrivilege.Source))
         End If
      Next
   End Sub
   Protected Sub SetMapPrivilegeDefaults( _
            ByVal privilege As MapPrivilege, _
            ByVal viewOrTable As IViewOrTable)

   End Sub

   Protected Sub SetMapObjectSearchCriteriaCollectionDefaults( _
            ByVal objectdef As MapObjectDef, _
            ByVal criterias As MapObjectSearchCriteriaCollection, _
            ByVal viewOrTable As IViewOrTable)
      Dim addPrimary As Boolean = True
      For Each criteria As MapSearchCriteria In criterias
         ' TODO: Actually check the columns as the programmer could have explicitly added the primarykey
         If Utility.IsCriteriaPrimaryKey(criteria, objectdef) Then
            addPrimary = False
         End If
      Next
      If addPrimary Then
         Dim criteria As New MapSearchCriteria(objectdef.MapMappingRoot, _
               primarykey, "Primary Key", True, Nothing)
         criterias.Add(criteria)
         If viewOrTable IsNot Nothing AndAlso viewOrTable.DBSPrimaryKeys IsNot Nothing Then
            For Each pk As DbsPrimaryKey In viewOrTable.DBSPrimaryKeys
               For Each keyfield As DbsPKField In pk.DbsPKFields
                  Dim column As IViewOrTableColumn = viewOrTable.ViewOrTableColumns(keyfield.Name)
                  criteria.MapSearchCriterions.Add(New MapSearchCriterion(criteria.MapMappingRoot, _
                           column.Name, column.Caption, column.OriginalName, _
                           viewOrTable.Name, column.NETType, Nothing))
               Next
            Next
         End If
      End If

   End Sub
   Protected Sub SetMapObjectSearchCriteriaDefaults( _
            ByVal criteria As MapSearchCriteria, _
            ByVal objectDef As MapObjectDef, _
            ByVal viewOrTable As IViewOrTable)
      criteria.IsPrimaryKeyCriteria = (Utility.IsCriteriaPrimaryKey(criteria, objectDef))
      If String.IsNullOrEmpty(criteria.Caption) Then
         criteria.Caption = Tools.GetCaption(criteria.Name)
      End If
   End Sub

   Protected Sub SetMapOrderByCollectionDefaults(ByVal objectdef As MapObjectDef, ByVal orderbies As MapOrderByCollection, ByVal viewOrTable As IViewOrTable)

   End Sub
   Protected Sub SetMapOrderByDefaults( _
            ByVal orderby As MapOrderBy, _
            ByVal index As Int32, _
            ByVal viewOrTable As IViewOrTable)
      If orderby.SortOrder = SortOrder.None Then
         orderby.SortOrder = SortOrder.Ascending
      End If
      If orderby.Ordinal.GetValueOrDefault = 0 Then
         orderby.Ordinal = index
      End If
   End Sub

   Protected Sub SetMapPropertyCollectionDefaults( _
            ByVal objectdef As MapObjectDef, _
            ByVal props As MapPropertyCollection, _
            ByVal viewOrTable As IViewOrTable)
      If viewOrTable IsNot Nothing AndAlso (props.Count = 0 OrElse objectdef.InferProperties.GetValueOrDefault) Then
         Dim viewTableNames As New List(Of String)
         For Each column As IViewOrTableColumn In viewOrTable.ViewOrTableColumns
            ' Skip the inferrence if it exists
            Dim exists As Boolean = False
            If props.GetPropertyByColumnName(column.OriginalName) Is Nothing AndAlso _
                     props.GetProperty(column.Name) Is Nothing Then
               ' TODO: Set a default in mapping for allow overrides or use a nullable column
               props.Add(New MapProperty(objectdef.MapMappingRoot, column.Name, _
                     column.OriginalName, viewOrTable.OriginalName, viewOrTable.OriginalName))
            End If
         Next
         viewTableNames.Add(viewOrTable.Name)
         AddJoinedColumns(viewTableNames, objectdef.MapJoinIns, props, viewOrTable)
         AddJoinedColumns(viewTableNames, objectdef.MapJoinBases, props, viewOrTable)
      End If
   End Sub
   Private Sub AddJoinedColumns( _
            ByVal viewTableNames As List(Of String), _
            ByVal joins As IMapJoinCollection, _
            ByVal props As MapPropertyCollection, _
            ByVal viewOrTable As IViewOrTable)
      For Each join As IMapJoin In joins
         Dim tableName As String = join.TableName
         Dim tableAlias As String = join.Alias
         If String.IsNullOrEmpty(tableAlias) Then
            tableAlias = join.TableName
         End If
         Do While viewTableNames.Contains(tableAlias)
            tableAlias = Utility.MakeAlias(tableAlias)
         Loop
         join.Alias = tableAlias
         For Each joinColumn As MapJoinInColumn In join.MapJoinInColumns
            ' TODO: Determine if joined in columns should be readonly 
            Dim columnAlias As String = joinColumn.Alias
            Dim name As String = joinColumn.Alias
            Dim existingProp As MapProperty = props.GetPropertyByColumnName(join.RightOriginalName, joinColumn.Alias)
            If existingProp Is Nothing Then
               Dim conflictingProp As MapProperty = props.GetProperty(columnAlias, True)
               If conflictingProp IsNot Nothing Then
                  columnAlias = join.Name & "_" & columnAlias
                  conflictingProp = props.GetProperty(columnAlias)
                  If conflictingProp IsNot Nothing Then
                     columnAlias = joinColumn.ColumnName
                     conflictingProp = props.GetProperty(columnAlias)
                     If conflictingProp IsNot Nothing Then
                        columnAlias = join.Name & "__" & columnAlias
                     Else
                        Utility.LogForUser("Could not create unique name", LogId.CanNotCreateName, CType(join, WrapperBase), joinColumn)
                     End If
                  End If
               End If
               props.Add(New MapProperty(join.MapMappingRoot, name, _
                     joinColumn.ColumnName, join.TableName, True, tableAlias, _
                     False, columnAlias))
            End If
         Next
         ' TODO: Nested joins currently not supported. MapJoinIns should allow nested JoinIns, but not bases. Will need some casting here.
         ' TODO: Nested joins currently not supported. MapJoinBases should allow nested JoinIns and bases. Will need some casting here.
         'For Each nestedJoinIn As MapJoinIn In join.MapJoinIns
         '   AddJoinedColumns(nestedJoinIn, props, table)
         'Next
      Next

   End Sub
   Protected Sub SetMapPropertyDefaults( _
            ByVal objectDef As MapObjectDef, _
            ByVal prop As MapProperty, _
            ByVal viewOrTable As IViewOrTable, _
            ByVal ordinal As Int32)
      Dim columnName As String = prop.ColumnName
      Dim inRootTable As Boolean = True
      Dim inBaseTable As Boolean = False
      If String.IsNullOrEmpty(columnName) Then
         columnName = prop.Name
      End If
      Dim column As IViewOrTableColumn = viewOrTable.ViewOrTableColumns(columnName)
      If column Is Nothing And Not String.IsNullOrEmpty(prop.TableName) Then
         Dim columnTable As DbsTable = viewOrTable.DbsDataStructures(0).DbsTables.GetTable(prop.TableName)
         If columnTable IsNot Nothing Then
            column = columnTable.DbsTableColumns(columnName)
         End If
         Dim join As IMapJoin = objectDef.MapJoinBases.GetByTableName(columnTable.OriginalName)
         inBaseTable = join IsNot Nothing
         inRootTable = False
      End If
      If column Is Nothing Then
         Utility.LogForUser("Can not find column", LogId.CanNotFindColumn, objectDef, CType(viewOrTable, WrapperBase), prop)
         Debug.WriteLine("column is missing")
         ' TODO: Output message
      End If
      ' TODO: Example of where we desperately need nullable values. Prop starts out as false, 
      ' so this can not check if the user set it to false. If the column does 
      ' not allow nulls, nulls should never be allowed. but if the column does allow nulls, '
      ' the property def should be able to disallow them
      If column IsNot Nothing Then
         prop.AllowNulls = column.AllowNulls
      End If
      If column IsNot Nothing AndAlso String.IsNullOrEmpty(prop.NETType) Then
         prop.NETType = column.NETType
      End If
      If String.IsNullOrEmpty(prop.BaseNETType) Then
         prop.BaseNETType = prop.NETType
      End If
      If column IsNot Nothing AndAlso String.IsNullOrEmpty(prop.Caption) Then
         If String.Compare(prop.ColumnName, prop.Name, StringComparison.InvariantCultureIgnoreCase) = 0 Then
            prop.Caption = column.Caption
         Else
            prop.Caption = KADGen.Utility.Tools.SpaceAtCaps(prop.Name)
         End If
      End If
      If column IsNot Nothing AndAlso String.IsNullOrEmpty(prop.ColumnName) Then
         prop.ColumnName = column.OriginalName
      End If
      If column IsNot Nothing AndAlso String.IsNullOrEmpty(prop.ColumnAlias) Then
         prop.ColumnAlias = prop.Name
      End If
      If String.IsNullOrEmpty(prop.CasedName) Then
         prop.CasedName = Utility.GetCasedName(prop.Name)
      End If
      If String.IsNullOrEmpty(prop.Default) Then
         ' TODO: Determine default
      End If
      If String.IsNullOrEmpty(prop.DefaultCSharp) Then
         ' TODO: Determine CSharp default from default
      End If
      If String.IsNullOrEmpty(prop.DefaultVB) Then
         ' TODO: Determine VB default from default
      End If
      If String.IsNullOrEmpty(prop.Empty) Then
         ' TODO: Detemrine empty
      End If
      If column IsNot Nothing AndAlso Not column.IsAutoIncrement.Equals(prop.IsAutoIncrement) Then
         prop.IsAutoIncrement = column.IsAutoIncrement
      End If
      ' 20070723 KAD Previously this tested against the table itself. This does not work for self joins. 
      '              So I changed the creation of the MapProperty for joins to set the value and stated
      '              testing that value here. 
      'If column IsNot Nothing AndAlso (inRootTable Or inBaseTable) AndAlso Not column.IsPrimaryKey.Equals(prop.IsPrimaryKey) Then
      If column IsNot Nothing AndAlso (inRootTable Or inBaseTable) AndAlso Not prop.IsPrimaryKey.HasValue Then
         prop.IsPrimaryKey = column.IsPrimaryKey
      End If
      If column IsNot Nothing AndAlso (prop.MaxLength.GetValueOrDefault = 0 OrElse prop.MaxLength.GetValueOrDefault > column.MaxLength.GetValueOrDefault) Then
         prop.MaxLength = column.MaxLength
      End If
      If prop.Ordinal.GetValueOrDefault = 0 Then
         ' This resets ordinal on zero and
         prop.Ordinal = ordinal + 1
      End If
      If column IsNot Nothing AndAlso String.IsNullOrEmpty(prop.OriginalName) Then
         prop.OriginalName = column.OriginalName
      End If
      If prop.Precision.GetValueOrDefault = 0 Then
         ' TODO: First, this a crappy test, second, we need a default value
      End If
      If prop.Scale.GetValueOrDefault = 0 Then
         ' TODO: First, this a crappy test, second, we need a default value
      End If
      If column IsNot Nothing AndAlso String.IsNullOrEmpty(prop.SQLType) Then
         prop.SQLType = column.SqlType
      End If
      If String.IsNullOrEmpty(prop.TableName) Then
         ' Joins are set when created, before we get here.
         prop.TableName = viewOrTable.OriginalName
      End If
      If String.IsNullOrEmpty(prop.Schema) Then
         prop.Schema = viewOrTable.Schema
      End If

      If column IsNot Nothing AndAlso column.Attributes IsNot Nothing Then
         For Each attribute As KADGen.MetadataWrapper.Attribute In column.Attributes
            ' If there is a conflict, the existing in the ORM file wins
            prop.AddCustomAttribute(attribute, False)
         Next
      End If

      ' TODO: Check for unique default
      ' TODO: Suport base that should not be readonly
      'If Not inBaseTable Then
      '   prop.ReadOnly = True
      'End If

   End Sub

   Protected Sub SetMapWhereClauseDefaults( _
            ByVal objectDef As MapObjectDef, _
            ByVal useSchemaInWhereClause As Boolean)
      ' This is similar code to the GetChildWhereClause, so any updates should consider both locations
      If String.IsNullOrEmpty(objectDef.WhereClause) Then
         Dim whereClause As New StringBuilder
         For i As Int32 = 0 To objectDef.PrimaryKeys.Count - 1
            Dim prop As MapProperty = objectDef.PrimaryKeys(i)
            If i > 0 Then
               whereClause.Append(" AND ")
            End If
            ' NOTE: This is SQL Server specific 
            If useSchemaInWhereClause Then
               whereClause.Append("@" & prop.Name & "=[" & prop.Schema & "].[" & prop.TableName & "].[" & prop.ColumnName & "]")
            Else
               whereClause.Append("@" & prop.Name & "=[" & prop.TableName & "].[" & prop.ColumnName & "]")
            End If
         Next
         objectDef.WhereClause = whereClause.ToString()
      End If
   End Sub

   Protected Sub SetMapRunSPCollectionDefaults(ByVal objectdef As MapObjectDef, ByVal runsps As MapRunSPCollection, ByVal viewOrTable As IViewOrTable)

   End Sub
   Protected Sub SetMapRunSPDefaults(ByVal runsp As MapRunSP, ByVal viewOrTable As IViewOrTable)

   End Sub

   Protected Sub SetMapSetSearchCriteriaCollectionDefaults(ByVal objectdef As MapObjectDef, ByVal criterias As MapSetSearchCriteriaCollection, ByVal viewOrTable As IViewOrTable)

   End Sub
   Protected Sub SetMapSetSearchCriteriaDefaults(ByVal criteria As MapSearchCriteria, ByVal viewOrTable As IViewOrTable)

   End Sub

   Protected Sub SetMapUseForDescCollectionDefaults( _
            ByVal objectdef As MapObjectDef, _
            ByVal descs As MapUseForDescCollection, _
            ByVal viewOrTable As IViewOrTable)
      ' We just set the UseForDesc property here and actually create them in the SetLate becasue
      ' its essential they be in the correct order. .NET templates will use them in the order of properties
      ' although stored procs wll be in the MapUseForDesc order.
      Dim found As Boolean
      If descs.Count > 0 Then
         found = True
         For Each desc As MapUseForDesc In descs
            Dim prop As MapProperty = objectdef.MapProperties.GetPropertyByPreferredName(objectdef.TableName, desc.Name, desc.ColumnName)
            If prop Is Nothing Then
               Utility.LogForUser("Can not find property for UseForDesc", LogId.CanNotFindProperty, objectdef, desc)
            Else
               prop.UseForDesc = True
            End If
         Next
      Else
         For Each prop As MapProperty In objectdef.MapProperties
            If prop.UseForDesc.GetValueOrDefault Then
               found = True
               Exit For
            End If
         Next
      End If

      If Not found Then
         Dim nameProperties As New List(Of MapProperty)
         Dim descProperties As New List(Of MapProperty)
         Dim allProperties As New List(Of MapProperty)
         For Each prop As MapProperty In objectdef.MapProperties
            If Not KADGen.Utility2005.Tools.IsSqlTypeNameVeryLarge(prop.SQLType) Then
               If IsNameColumn(prop.Name) Then
                  nameProperties.Add(prop)
               ElseIf IsDescColumn(prop.Name) Then
                  descProperties.Add(prop)
               ElseIf Not prop.IsPrimaryKey.GetValueOrDefault Then
                  allProperties.Add(prop)
               End If
            End If
         Next

         Dim propertiesToAdd As List(Of MapProperty)
         If nameProperties.Count > 0 Then
            propertiesToAdd = nameProperties
         ElseIf descProperties.Count > 0 Then
            propertiesToAdd = descProperties
         Else
            propertiesToAdd = allProperties
         End If
         For Each prop As MapProperty In propertiesToAdd
            found = True
            prop.UseForDesc = True
         Next
      End If

      ' We can't infer it intelligently, include all columns from the main table
      If Not found Then
         For Each prop As MapProperty In objectdef.MapProperties
            If prop.TableName = objectdef.TableName Then
               prop.UseForDesc = True
            End If
         Next
      End If

      'For Each prop As MapProperty In objectdef.MapProperties
      '   If prop.UseForDesc Then
      '      Dim desc As MapUseForDesc = descs(prop.Name)
      '      If desc Is Nothing Then
      '         desc = New MapUseForDesc(objectdef.MapMappingRoot, prop.Name, prop.ColumnName, prop.TableName, True, Nothing, Nothing, Nothing, Nothing)
      '         descs.Add(desc)
      '      End If
      '   End If
      'Next
      'If descs.Count = 0 Then
      '   Dim nameProperties As New List(Of MapUseForDesc)
      '   Dim descProperties As New List(Of MapUseForDesc)
      '   Dim allProperties As New List(Of MapUseForDesc)
      '   For Each prop As MapProperty In objectdef.MapProperties
      '      If IsNameColumn(prop.Name) Then
      '         nameProperties.Add(New MapUseForDesc(objectdef.MapMappingRoot, prop.Name, prop.ColumnName, prop.TableName))
      '      ElseIf IsDescColumn(prop.Name) Then
      '         descProperties.Add(New MapUseForDesc(objectdef.MapMappingRoot, prop.Name, prop.ColumnName, prop.TableName))
      '      ElseIf Not prop.IsPrimaryKey Then
      '         allProperties.Add(New MapUseForDesc(objectdef.MapMappingRoot, prop.Name, prop.ColumnName, prop.TableName))
      '      End If
      '   Next

      '   Dim propertiesToAdd As List(Of MapUseForDesc)
      '   If nameProperties.Count > 0 Then
      '      propertiesToAdd = nameProperties
      '   ElseIf descProperties.Count > 0 Then
      '      propertiesToAdd = descProperties
      '   Else
      '      propertiesToAdd = allProperties
      '   End If
      '   For Each useForDesc As MapUseForDesc In propertiesToAdd
      '      descs.Add(useForDesc)
      '   Next
      'End If
      '' We can't infer it intelligently, include all columns from the main table
      'If descs.Count = 0 Then
      '   For Each prop As MapProperty In objectdef.MapProperties
      '      If prop.TableName = objectdef.TableName Then
      '         descs.Add(New MapUseForDesc(objectdef.MapMappingRoot, prop.Name, prop.ColumnName, prop.TableName, True, Nothing, Nothing, Nothing, Nothing))
      '      End If
      '   Next
      'End If
   End Sub
   Private Function IsNameColumn(ByVal name As String) As Boolean
      ' TODO: Update to use localized comma delimited array
      Return name.ToLower().Contains("name")
   End Function
   Private Function IsDescColumn(ByVal name As String) As Boolean
      ' TODO: Update to use localized comma delimited array
      Return name.ToLower().Contains("desc")
   End Function
   Protected Sub SetMapUseForDescDefaults(ByVal desc As MapUseForDesc, ByVal viewOrTable As IViewOrTable)

   End Sub

   Protected Sub SetMapUseForDescSetCollectionDefaults(ByVal objectdef As MapObjectDef, ByVal descSets As MapUseForDescSetCollection, ByVal viewOrTable As IViewOrTable)

   End Sub
   Protected Sub SetMapUseForDescSetDefaults(ByVal descSet As MapUseForDescSet, ByVal viewOrTable As IViewOrTable)

   End Sub


   Protected Sub SetLateUseForDesc(ByVal objectDef As MapObjectDef)
      'For Each prop As MapProperty In objectDef.MapProperties
      '   If prop.UseForDesc Then
      '      Dim desc As MapUseForDesc = descs(prop.Name)
      '      If desc Is Nothing Then
      '         desc = New MapUseForDesc(objectDef.MapMappingRoot, prop.Name, prop.ColumnName, prop.TableName, True, Nothing, Nothing, Nothing, Nothing)
      '         descs.Add(desc)
      '      End If
      '   End If
      'Next
      Dim descs As MapUseForDescCollection = objectDef.MapUseForDescs
      For Each primaryKeyProperty As MapProperty In objectDef.PrimaryKeys
         primaryKeyProperty.UseForDesc = True
         'Dim desc As MapUseForDesc = descs(primaryKeyProperty.Name)
         'If desc Is Nothing Then
         '   desc = New MapUseForDesc(objectDef.MapMappingRoot, primaryKeyProperty.Name, _
         '            primaryKeyProperty.ColumnName, primaryKeyProperty.TableName, True, _
         '            Nothing, Nothing, Nothing, Nothing)
         '   descs.Add(desc)
         'End If
      Next
      ' We have to set all the UseForDesc attributes, then create the MapUseForDesc here because its 
      ' essential that the order of MapUseForDesc be the same as the order of properties. Otherwise, 
      ' the stored proc and business object are out of sync and create errors. 
      objectDef.MapUseForDescs.Clear()
      For Each prop As MapProperty In objectDef.MapProperties
         If prop.UseForDesc.GetValueOrDefault Then
            objectDef.MapUseForDescs.Add(New MapUseForDesc(objectDef.MapMappingRoot, prop.Name, prop.ColumnName, prop.TableName))
         End If
      Next
   End Sub

   Protected Sub SetLateObjectDisplayName(ByVal objectDef As MapObjectDef)
      For Each prop As MapProperty In objectDef.MapProperties
         If prop.UseForDesc.GetValueOrDefault Then
            objectDef.DisplayName = prop.Name
            Exit Sub
         End If
      Next
   End Sub

   Protected Sub SetLateAliases(ByVal objectDef As MapObjectDef)
      Dim nameList As NameList = Defaults.NameList.GetAliasNameList(objectDef)
      Dim name As String = objectDef.TableName
      If name Is Nothing Then
         name = objectDef.ViewName
      End If
      GetAlias(nameList, name) ' this is always the first, so we do not need to assign
      For Each child As MapChild In objectDef.MapChildren
         Dim aliasName As String = GetAlias(nameList, child.Alias)
         If aliasName <> child.Alias Then
            For Each key As MapRelationKey In child.MapRelationKeys
               If key.ChildAlias = child.Alias Then
                  key.ChildAlias = aliasName
               End If
            Next
            child.Alias = aliasName
         End If
         For Each key As MapRelationKey In child.MapRelationKeys
            If String.IsNullOrEmpty(key.ParentAlias) Then
               key.ParentAlias = key.ParentTable
            End If
            If String.IsNullOrEmpty(key.ChildAlias) Then
               key.ChildAlias = key.ChildTable
            End If
         Next
      Next
      'SetAliases(nameList, objectDef.MapJoinIns)
      'SetAliases(nameList, objectDef.MapJoinBases)
   End Sub

   Protected Sub SetLateLookups(ByVal objectDef As MapObjectDef)
      Dim nonPrimaryKeys As MapPropertyCollection = objectDef.NonPrimaryKeys
      If Not objectDef.IsLookup.GetValueOrDefault AndAlso _
               Not objectDef.MapMapping.NoInferrence.GetValueOrDefault And _
               Not objectDef.MapMapping.NoInferLookups.GetValueOrDefault And _
               Not objectDef.NoImplicitLookup.GetValueOrDefault Then
         If nonPrimaryKeys.Count <= 2 Then
            For Each prop As MapProperty In nonPrimaryKeys
               If String.Compare(prop.Name, My.Resources.Desc, True) = 0 Or _
                  String.Compare(prop.Name, My.Resources.Description, True) = 0 Then
                  objectDef.IsLookup = True
               End If
            Next
         End If
      End If
   End Sub

   Protected Sub SetLateObjectSearchCriterias( _
            ByVal objectDef As MapObjectDef, _
            ByVal datastructure As DbsDataStructure)
      For Each criteria As MapSearchCriteria In objectDef.MapObjectSearchCriterias
         SetLateObjectSearchCriteria(objectDef, criteria)
      Next
   End Sub

   Protected Sub SetLateSetSearchCriterias( _
            ByVal objectDef As MapObjectDef, _
            ByVal datastructure As DbsDataStructure)
      For Each criteria As MapSearchCriteria In objectDef.MapSetSearchCriterias
         SetLateObjectSearchCriteria(objectDef, criteria)
      Next
   End Sub

   Protected Sub SetLateObjectSearchCriteria( _
            ByVal objectDef As MapObjectDef, _
            ByVal criteria As MapSearchCriteria)
      If criteria.MapSearchCriterions.Count = 0 Then
         ' Assume the name of the criteria is the name of the only key involved. 
         Dim criterion As MapSearchCriterion = Nothing
         For Each prop As MapProperty In objectDef.MapProperties
            If prop.Name = criteria.Name Then
               criterion = New MapSearchCriterion(objectDef.MapMappingRoot, _
                              criteria.Name, prop.Caption, prop.ColumnName, prop.TableName, prop.NETType, prop.Schema)
            End If
         Next
         If criterion Is Nothing Then
            For Each prop As MapProperty In objectDef.MapProperties
               If prop.ColumnName = criteria.Name Then
                  criterion = New MapSearchCriterion(objectDef.MapMappingRoot, _
                                 Nothing, Nothing, criteria.Name, Nothing, Nothing, Nothing)
               End If
            Next
         End If
         If criterion Is Nothing Then
            Utility.LogForUser("Could not infer criterion from criteria name", LogId.InferrenceFailureCriteria, objectDef, criteria)
         Else
            criteria.MapSearchCriterions.Add(criterion)
         End If
      End If
      For Each criterion As MapSearchCriterion In criteria.MapSearchCriterions
         Dim prop As MapProperty = objectDef.MapProperties.GetPropertyByPreferredName(objectDef.TableName, criterion.Name, criterion.ColumnName)
         If prop Is Nothing Then
            Utility.LogForUser("Property could not be found for criterion", LogId.CanNotFindProperty, objectDef, criteria, criterion)
         Else
            If String.IsNullOrEmpty(criterion.Name) Then
               criterion.Name = prop.Name
            End If
            If String.IsNullOrEmpty(criterion.ColumnName) Then
               criterion.ColumnName = prop.ColumnName
            End If
            If String.IsNullOrEmpty(criterion.Caption) Then
               criterion.Caption = prop.Caption
            End If
            If String.IsNullOrEmpty(criterion.NETType) Then
               criterion.NETType = prop.NETType
            End If
            If String.IsNullOrEmpty(criterion.TableName) Then
               criterion.TableName = prop.TableName
            End If
            If String.IsNullOrEmpty(criterion.Schema) Then
               criterion.Schema = prop.Schema
            End If
         End If
      Next
   End Sub

   Private Sub SetLateDependentProperties( _
            ByVal objectDef As MapObjectDef, _
            ByVal datastructure As DbsDataStructure)
      For Each join As MapJoinBase In objectDef.MapJoinBases
         SetLateDependentPropertiesForJoin(objectDef, join)
      Next
   End Sub

   Protected Sub SetLateDependentPropertiesForJoin( _
            ByVal objectDef As MapObjectDef, _
            ByVal join As MapJoinBase)
      For Each joinKey As MapJoinKey In join.MapJoinKeys
         ' We expect only one, the order may be ditzed if there are multiples
         Dim rootProp As MapProperty = objectDef.MapProperties.GetPropertyByColumnName(join.RightOriginalName, joinKey.RightColumn)
         Dim leafProp As MapProperty = objectDef.MapProperties.GetPropertyByColumnName(join.LeftOriginalName, joinKey.LeftColumn)
         leafProp.DependentTableName = rootProp.TableName
         leafProp.DependentColumnName = rootProp.ColumnName
         rootProp.DependentTableName = leafProp.TableName
         rootProp.DependentColumnName = leafProp.ColumnName
         rootProp.JoinBaseRootKey = True
         leafProp.JoinBaseLeafKey = True
      Next
   End Sub

   Private Sub SetLateJoinKeys(ByVal objectDef As MapObjectDef)
      For Each join As MapJoinBase In objectDef.MapJoinBases
         For Each joinKey As MapJoinKey In join.MapJoinKeys
            Dim rootProp As MapProperty = objectDef.MapProperties.GetPropertyByColumnName( _
                     join.RightOriginalName, joinKey.RightColumn)
            Dim leafProp As MapProperty = objectDef.MapProperties.GetPropertyByColumnName( _
                     join.LeftOriginalName, joinKey.LeftColumn)
            mKeyId += 1
            joinKey.RightColumnKey = "key_" & mKeyId.ToString() & "_" & joinKey.RightColumn
            joinKey.IsAutoIncrement = rootProp.IsAutoIncrement
            joinKey.SQLType = rootProp.SQLType
            joinKey.LeafKeyIsPrimary = leafProp.IsPrimaryKey
         Next
      Next
   End Sub
   'Private Sub SetAliases(ByVal namelist As NameList, ByVal joins As IMapJoinCollection)
   '   For Each join As IMapJoin In joins
   '      Dim aliasName As String = GetAlias(namelist, join.Alias)
   '      If aliasName <> join.Alias Then
   '         join.Alias = aliasName
   '      End If
   '      ' TODO: Add nesting support for JOinIn and JoinBase (JoinBase only)
   '   Next

   'End Sub

   Private Function GetAlias(ByVal nameList As NameList, ByVal name As String) As String
      If nameList.ContainsKey(name) Then
         Dim counts As Int32() = nameList(name)
         Dim retValue As String
         If counts(0) = 1 Or counts(1) = 0 Then
            ' This is the first thing with this name
            retValue = name
         Else
            ' Double underscore is used because almost no one uses double underscore in their table name 
            ' and if the original database has a table named "Cust" and one named "Cust_1" we don't want 
            ' to collide
            retValue = name & "__" & counts(1).ToString
         End If
         counts(1) += 1
         If counts(1) > counts(0) Then
            Throw New System.Exception("Counts are corrupted")
         End If
         Return retValue
      Else
         Throw New System.Exception("Name is missing from nameList")
      End If
   End Function

#Region "Public properties"
   Public Property DefaultGenerate() As String
      Get
         Return Me.mDefaultGenerate
      End Get
      Protected Set(ByVal value As String)
         Me.mDefaultGenerate = value
      End Set
   End Property

   Public Property CreatePattern() As String
      Get
         Return Me.mCreatePattern
      End Get
      Protected Set(ByVal value As String)
         Me.mCreatePattern = value
      End Set
   End Property

   Public Property RetrievePattern() As String
      Get
         Return Me.mRetrievePattern
      End Get
      Protected Set(ByVal value As String)
         Me.mRetrievePattern = value
      End Set
   End Property

   Public Property RetrieveChildrenPattern() As String
      Get
         Return Me.mRetrieveChildrenPattern
      End Get
      Protected Set(ByVal value As String)
         Me.mRetrieveChildrenPattern = value
      End Set
   End Property

   Public Property RetrieveHierarchyPattern() As String
      Get
         Return Me.mRetrieveHierarchyPattern
      End Get
      Protected Set(ByVal value As String)
         Me.mRetrieveHierarchyPattern = value
      End Set
   End Property

   Public Property RetrieveAlternatePattern() As String
      Get
         Return Me.mRetrieveAlternatePattern
      End Get
      Protected Set(ByVal value As String)
         Me.mRetrieveAlternatePattern = value
      End Set
   End Property

   Public Property UpdatePattern() As String
      Get
         Return Me.mUpdatePattern
      End Get
      Protected Set(ByVal value As String)
         Me.mDefaultGenerate = value
      End Set
   End Property

   Public Property DeletePattern() As String
      Get
         Return Me.mDeletePattern
      End Get
      Protected Set(ByVal value As String)
         Me.mDeletePattern = value
      End Set
   End Property

   Public Property SetSelectPattern() As String
      Get
         Return Me.mSetSelectPattern
      End Get
      Protected Set(ByVal value As String)
         Me.mSetSelectPattern = value
      End Set
   End Property

   Public ReadOnly Property DefaultPriveleges() As MapPrivilegeCollection
      Get
         Return Me.mDefaultPriveleges
      End Get
   End Property
#End Region

   Private Class NameList
      Inherits Dictionary(Of String, Int32())

      Friend Shared Function GetAliasNameList(ByVal objectDef As MapObjectDef) _
               As NameList
         Dim nameList As New NameList
         Dim name As String = objectDef.TableName
         If name Is Nothing Then
            name = objectDef.ViewName
         End If
         nameList.AddName(name)
         For Each child As MapChild In objectDef.MapChildren
            nameList.AddName(child.Alias)
         Next
         AddJoins(nameList, objectDef.MapJoinIns)
         AddJoins(nameList, objectDef.MapJoinBases)
         Return nameList
      End Function

      Private Shared Sub AddJoins( _
                  ByVal nameList As NameList, _
                  ByVal mapJoinIns As IMapJoinCollection)
         For Each join As IMapJoin In mapJoinIns
            nameList.AddName(join.Alias)
            ' TODO: Add support for nested join ins and join bases (join bases only)
         Next
      End Sub

      Friend Sub AddName(ByVal name As String)
         If Me.ContainsKey(name) Then
            Dim counts As Int32() = Me(name)
            counts(0) += 1
         Else
            Me.Add(name, New Int32() {1, 0})
         End If
      End Sub
   End Class

End Class
